[Twisted-Python] startTLS errors not propagating to Factory
Richard van der Hoff
richard at matrix.org
Wed Apr 28 15:43:56 MDT 2021
On 28/04/2021 07:06, Glyph wrote:
>
>> Is the SMTP code holding the Factory
>> wrong? Or is it reasonable to expect the verification error to
>> propagate into clientConnectionFailed - in which case, how could this
>> work?
>>
>> Thanks for your thoughts!
>
> Hi Richard,
>
> Sorry for the delayed response here.
>
> This is a bug in Twisted, and I think it boils down to this line:
> https://github.com/twisted/twisted/blob/3c868ac11786eef7ea269caa3056f00854128957/src/twisted/protocols/tls.py#L391
>
>
> The code as written here appears to be expecting this sequence:
>
> 1. failVerification is called with a reason containing a helpful
> OpenSSL verification error
> 2. we save that reason as `self._reason` for reporting later, calling
> abortConnection()
> 3. since the connection got aborted, we expect our underlying transport
> to call loseConnection on us
> 4. we will then get a falsey reason [?!?!] and as such we will use
> self._reason instead
>
>
> Assumption 4 is nonsense and has never been true within Twisted as far
> as I know; connectionLost always gets a Failure, Failures are never
> falsey, so we will never use self._reason. To fix this we need to
> actually honor self._reason under the conditions we expect, i.e. it's a
> ConnectionAborted
> https://github.com/twisted/twisted/blob/3c868ac11786eef7ea269caa3056f00854128957/src/twisted/internet/error.py#L209
Thanks very much for your thoughts on this, Glyph - it's always helpful
to have an insight into the intended design when trying to resolve this
sort of thing.
I don't follow your reasoning though. I think you might have misread the
line you point to
(https://github.com/twisted/twisted/blob/3c868ac11786eef7ea269caa3056f00854128957/src/twisted/protocols/tls.py#L391).
It is "self._reason or reason" - ie, if self._reason is already set, it
will take precedence over reason.
In my tests at least, TLSMemoryBIOProtocol.connectionLost is doing
exactly the right thing - it is called with an unhelpful reason, but
substitutes back in the helpful reason which has already been stashed.
Rather, the problem, as I see it, is that it's not
TLSMemoryBIOProtocol.connectionLost that calls
Factory.clientConnectionLost. That is done by tcp.Client.connectionLost,
via one of tcp.Client's myriad of base classes, at
https://github.com/twisted/twisted/blob/3c868ac11786eef7ea269caa3056f00854128957/src/twisted/internet/tcp.py#L508.
Of course, that doesn't get the benefit of TLSMemoryBIOProtocol's reason
switcheroo.
I'm still not quite sure who is in the wrong here.
Cheers
Richard
PS: yes, once we figure out what's going wrong here, I'll at least write
up an issue...
More information about the Twisted-Python
mailing list