BIO_CTRL_PUSH is an optional value that is not handled in the tlsBIO:BioCtrl().
The larger problem is that the library does not support new optional commands because it returns -2 for unknown cmds in BioCtrl(). I would suggest changing the default return value to 0. I confirmed that this fixed the issue.
tcltls version: 1.8.0 (trunk as of today)
OS: FreeBSD 12.3
Openssl version: 1.1.1q
Patch
--- tlsBIO.c
+++ tlsBIO.c
@@ -279,11 +279,11 @@
ret = ((Tcl_WriteRaw(chan, "", 0) >= 0) ? 1 : -1);
dprintf("BIO_CTRL_FLUSH returning value %li", ret);
break;
default:
dprintf("Got unknown control command (%i)", cmd);
- ret = -2;
+ ret = 0;
break;
}
return(ret);
}
Example of problem
package require tls
./tls.c:1785:Tls_Init():Called
./tls.c:1903:TlsLibInit():Called
./tlsBIO.c:53:BIO_new_tcl():BIO_new_tcl() called
./tlsBIO.c:66:BIO_new_tcl():Asked to setup a NULL state, just creating the initial configuration
1.8.0
% set sock [tls::socket listener.logz.io 5052]
./tls.c:759:ImportObjCmd():Called
./tls.c:1093:CTX_Init():Called
./tls.c:925:ImportObjCmd():Consuming Tcl channel sock8010d2690
./tls.c:927:ImportObjCmd():Created channel named sock8010d2690
./tlsIO.c:699:TlsWatchProc():TlsWatchProc(0x0)
./tlsIO.c:708:TlsWatchProc():statePtr->flags=0|TLS_TCL_INIT
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsIO.c:734:TlsWatchProc():Registering our interest in the lower channel (chan=0x80105e050)
./tlsIO.c:699:TlsWatchProc():TlsWatchProc(0x0)
./tlsIO.c:708:TlsWatchProc():statePtr->flags=0|TLS_TCL_INIT
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsIO.c:734:TlsWatchProc():Registering our interest in the lower channel (chan=0x80105e050)
./tlsBIO.c:53:BIO_new_tcl():BIO_new_tcl() called
./tlsBIO.c:292:BioNew():BioNew(0x80092f680) called
./tls.c:991:ImportObjCmd():Returning sock8010d2690
sock8010d2690
% tls::handshake $sock
./tls.c:647:HandshakeObjCmd():Called
./tls.c:669:HandshakeObjCmd():Calling Tls_WaitForConnect
./tlsIO.c:197:Tls_WaitForConnect():WaitForConnect(0x80107c010)
./tlsIO.c:198:Tls_WaitForConnect():statePtr->flags=0|TLS_TCL_INIT
./tlsIO.c:228:Tls_WaitForConnect():Calling SSL_connect()
./tls.c:180:InfoCallback():Called
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:229:BioCtrl():BioCtrl(0x80092f680, 0x6, 0x0, 0x80092f780)
./tlsBIO.c:283:BioCtrl():Got unknown control command (6)
./tls.c:180:InfoCallback():Called
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:120:BioWrite():[chan=0x80105e050] BioWrite(0x80092f680, <buf>, 517)
./tlsBIO.c:127:BioWrite():[chan=0x80105e050] BioWrite(517) -> 517 [tclEof=0; tclErrno=0]
./tlsBIO.c:148:BioWrite():Successfully wrote some data
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:229:BioCtrl():BioCtrl(0x80092f680, 0xb, 0x0, 0x0)
./tlsBIO.c:278:BioCtrl():Got BIO_CTRL_FLUSH
./tlsBIO.c:280:BioCtrl():BIO_CTRL_FLUSH returning value 1
./tls.c:180:InfoCallback():Called
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:169:BioRead():[chan=0x80105e050] BioRead(0x80092f680, <buf>, 5)
./tlsBIO.c:180:BioRead():[chan=0x80105e050] BioRead(5) -> 5 [tclEof=0; tclErrno=0]
./tlsBIO.c:201:BioRead():Successfully read some data
./tlsBIO.c:212:BioRead():BioRead(0x80092f680, <buf>, 5) [0x80105e050] returning 5
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:169:BioRead():[chan=0x80105e050] BioRead(0x80092f680, <buf>, 122)
./tlsBIO.c:180:BioRead():[chan=0x80105e050] BioRead(122) -> 122 [tclEof=0; tclErrno=0]
./tlsBIO.c:201:BioRead():Successfully read some data
./tlsBIO.c:212:BioRead():BioRead(0x80092f680, <buf>, 122) [0x80105e050] returning 122
./tls.c:180:InfoCallback():Called
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:169:BioRead():[chan=0x80105e050] BioRead(0x80092f680, <buf>, 5)
./tlsBIO.c:180:BioRead():[chan=0x80105e050] BioRead(5) -> 5 [tclEof=0; tclErrno=0]
./tlsBIO.c:201:BioRead():Successfully read some data
./tlsBIO.c:212:BioRead():BioRead(0x80092f680, <buf>, 5) [0x80105e050] returning 5
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:169:BioRead():[chan=0x80105e050] BioRead(0x80092f680, <buf>, 1)
./tlsBIO.c:180:BioRead():[chan=0x80105e050] BioRead(1) -> 1 [tclEof=0; tclErrno=0]
./tlsBIO.c:201:BioRead():Successfully read some data
./tlsBIO.c:212:BioRead():BioRead(0x80092f680, <buf>, 1) [0x80105e050] returning 1
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:169:BioRead():[chan=0x80105e050] BioRead(0x80092f680, <buf>, 5)
./tlsBIO.c:180:BioRead():[chan=0x80105e050] BioRead(5) -> 5 [tclEof=0; tclErrno=0]
./tlsBIO.c:201:BioRead():Successfully read some data
./tlsBIO.c:212:BioRead():BioRead(0x80092f680, <buf>, 5) [0x80105e050] returning 5
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:169:BioRead():[chan=0x80105e050] BioRead(0x80092f680, <buf>, 23)
./tlsBIO.c:180:BioRead():[chan=0x80105e050] BioRead(23) -> 23 [tclEof=0; tclErrno=0]
./tlsBIO.c:201:BioRead():Successfully read some data
./tlsBIO.c:212:BioRead():BioRead(0x80092f680, <buf>, 23) [0x80105e050] returning 23
./tls.c:180:InfoCallback():Called
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:169:BioRead():[chan=0x80105e050] BioRead(0x80092f680, <buf>, 5)
./tlsBIO.c:180:BioRead():[chan=0x80105e050] BioRead(5) -> 5 [tclEof=0; tclErrno=0]
./tlsBIO.c:201:BioRead():Successfully read some data
./tlsBIO.c:212:BioRead():BioRead(0x80092f680, <buf>, 5) [0x80105e050] returning 5
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:169:BioRead():[chan=0x80105e050] BioRead(0x80092f680, <buf>, 5673)
./tlsBIO.c:180:BioRead():[chan=0x80105e050] BioRead(5673) -> 5673 [tclEof=0; tclErrno=0]
./tlsBIO.c:201:BioRead():Successfully read some data
./tlsBIO.c:212:BioRead():BioRead(0x80092f680, <buf>, 5673) [0x80105e050] returning 5673
./tls.c:180:InfoCallback():Called
./tls.c:283:VerifyCallback():Verify: 0
./tls.c:283:VerifyCallback():Verify: 1
./tls.c:283:VerifyCallback():Verify: 1
./tls.c:283:VerifyCallback():Verify: 1
./tls.c:283:VerifyCallback():Verify: 1
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:169:BioRead():[chan=0x80105e050] BioRead(0x80092f680, <buf>, 5)
./tlsBIO.c:180:BioRead():[chan=0x80105e050] BioRead(5) -> 5 [tclEof=0; tclErrno=0]
./tlsBIO.c:201:BioRead():Successfully read some data
./tlsBIO.c:212:BioRead():BioRead(0x80092f680, <buf>, 5) [0x80105e050] returning 5
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:169:BioRead():[chan=0x80105e050] BioRead(0x80092f680, <buf>, 281)
./tlsBIO.c:180:BioRead():[chan=0x80105e050] BioRead(281) -> 281 [tclEof=0; tclErrno=0]
./tlsBIO.c:201:BioRead():Successfully read some data
./tlsBIO.c:212:BioRead():BioRead(0x80092f680, <buf>, 281) [0x80105e050] returning 281
./tls.c:180:InfoCallback():Called
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:169:BioRead():[chan=0x80105e050] BioRead(0x80092f680, <buf>, 5)
./tlsBIO.c:180:BioRead():[chan=0x80105e050] BioRead(5) -> 5 [tclEof=0; tclErrno=0]
./tlsBIO.c:201:BioRead():Successfully read some data
./tlsBIO.c:212:BioRead():BioRead(0x80092f680, <buf>, 5) [0x80105e050] returning 5
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:169:BioRead():[chan=0x80105e050] BioRead(0x80092f680, <buf>, 69)
./tlsBIO.c:180:BioRead():[chan=0x80105e050] BioRead(69) -> 69 [tclEof=0; tclErrno=0]
./tlsBIO.c:201:BioRead():Successfully read some data
./tlsBIO.c:212:BioRead():BioRead(0x80092f680, <buf>, 69) [0x80105e050] returning 69
./tls.c:180:InfoCallback():Called
./tls.c:180:InfoCallback():Called
./tls.c:180:InfoCallback():Called
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:120:BioWrite():[chan=0x80105e050] BioWrite(0x80092f680, <buf>, 80)
./tlsBIO.c:127:BioWrite():[chan=0x80105e050] BioWrite(80) -> 80 [tclEof=0; tclErrno=0]
./tlsBIO.c:148:BioWrite():Successfully wrote some data
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:229:BioCtrl():BioCtrl(0x80092f680, 0xb, 0x0, 0x0)
./tlsBIO.c:278:BioCtrl():Got BIO_CTRL_FLUSH
./tlsBIO.c:280:BioCtrl():BIO_CTRL_FLUSH returning value 1
./tls.c:180:InfoCallback():Called
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:229:BioCtrl():BioCtrl(0x80092f680, 0x7, 0x0, 0x80092f780)
./tlsBIO.c:283:BioCtrl():Got unknown control command (7)
./tls.c:180:InfoCallback():Called
./tls.c:180:InfoCallback():Called
./tlsIO.c:234:Tls_WaitForConnect():That seems to have gone okay
./tlsIO.c:972:Tls_GetParent():Requested to get parent of channel 0x801085090
./tlsBIO.c:229:BioCtrl():BioCtrl(0x80092f680, 0xb, 0x0, 0x0)
./tlsBIO.c:278:BioCtrl():Got BIO_CTRL_FLUSH
./tlsBIO.c:280:BioCtrl():BIO_CTRL_FLUSH returning value 1
./tlsIO.c:245:Tls_WaitForConnect():Got error: 1 (rc = 0)
./tlsIO.c:278:Tls_WaitForConnect():We have either completely established the session or completely failed it -- there is no more need to ever retry it though
./tlsIO.c:288:Tls_WaitForConnect():The connection is up
./tlsIO.c:348:Tls_WaitForConnect():Removing the "TLS_TCL_INIT" flag since we have completed the handshake
./tlsIO.c:351:Tls_WaitForConnect():Returning in success
./tls.c:671:HandshakeObjCmd():Tls_WaitForConnect returned: 0
./tls.c:699:HandshakeObjCmd():Returning TCL_OK with data "1"
Ignoring all unknown controls is not a good idea.
Since not all OpenSSL versions and variants support "BIO_CTRL_POP" and "BIO_CTRL_PUSH", the following is change is a more proper patch.
This was tested with Tcl 8.6.13, tcltls-1.7.22 and OpenSSL 3.1.3 (19 Sep 2023).
--- tlsBIO.c-orig 2023-10-21 17:38:57
+++ tlsBIO.c 2023-10-22 11:32:02
@@ -278,7 +278,15 @@
dprintf("Got BIO_CTRL_FLUSH");
ret = ((Tcl_WriteRaw(chan, "", 0) >= 0) ? 1 : -1);
dprintf("BIO_CTRL_FLUSH returning value %li", ret);
+ break;
+#ifdef BIO_CTRL_POP
+ case BIO_CTRL_POP:
+ dprintf("Got BIO_CTRL_POP");
+ break;
+ case BIO_CTRL_PUSH:
+ dprintf("Got BIO_CTRL_PUSH");
break;
+#endif
default:
dprintf("Got unknown control command (%i)", cmd);
ret = -2;