[Python-Dev] Proposal for better SSL errors

Terry Reedy tjreedy at udel.edu
Sat May 26 23:44:08 CEST 2012


On 5/26/2012 3:28 PM, Antoine Pitrou wrote:
>
> Hello,
>
> In http://bugs.python.org/issue14837 I have attached a proof-of-concept
> patch to improve the exceptions raised by the ssl module when OpenSSL
> signals an error. The current situation is quite dismal, since you get
> a sometimes cryptic error message with no viable opportunities for
> programmatic introspection:
>
>>>> ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
>>>> ctx.verify_mode = ssl.CERT_REQUIRED
>>>> sock = socket.create_connection(("svn.python.org", 443))
>>>> sock = ctx.wrap_socket(sock)
> Traceback (most recent call last):
> [...]
> ssl.SSLError: [Errno 1] _ssl.c:420: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

I agree that this is not easy to read ;-)

> SSLError instances only have a "errno" attribute which doesn't actually
> contain a meaningful value.
>
> With the posted patch, the above error becomes:
>
>>>> ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
>>>> ctx.verify_mode = ssl.CERT_REQUIRED
>>>> sock = socket.create_connection(("svn.python.org", 443))
>>>> sock = ctx.wrap_socket(sock)
> Traceback (most recent call last):
> [...]
> ssl.SSLError: [Errno 5] [SSL: CERTIFICATE_VERIFY_FAILED] certificate
> verify failed (_ssl.c:494) [88296 refs]

Repeating the same reason in upper and lower case is unhelpful noise. 
Here is my suggested human-readable message.

ssl.SSLError: in ssl sublibrary, certificate verify failed

> Not only does the error string contain more valuable information (the
> mnemonics "SSL" and "CERTIFICATE_VERIFY_FAILED" indicate, respectively,
> in which subpart of OpenSSL and which precise error occurred), but they
> are also introspectable:
>
>>>> e = sys.last_value
>>>> e.library
> 'SSL'

Not being up on ssl sublibraries, I would tend to think that means the 
main ssl library that gets imported. If that is wrong, .sublibrary would 
be clearer to me, but knowledgable users may be fine with it as it is.

>>>> e.reason
> 'CERTIFICATE_VERIFY_FAILED'
>
> (these mnemonics correspond to OpenSSL's own #define'd numeric codes. I
> find it more Pythonic to expose the mnemonics than the numbers, though.
> Of course, the numbers<->  mnemnonics mappings can be separately
> exposed)

Python is not a 'minimize characters written' language and library. 
Inside an exception branch,
      if e.reason == 'CERTIFICATE_VERIFY_FAILED':
is really clear, more so than any abbreviation.

> You'll note there is still a "Errno 5" in that error message; I don't
> really know what to do with it. Hard-wiring the errno attribute to
> something like None *might* break existing software, although that
> would be unlikely since the current errno value is quite meaningless
> and confusing (it has nothing to do with POSIX errnos).

Given what you have written, I think the aim should be to get rid of it. 
If you want to be conservative and not just delete it now, give SSLError 
a __getattr__(self,name) method that looks for name == 'errno' and when 
so, issues a DeprecationWarning "SSLError.errno is meaningless and will 
be removed in the future. It is currently fixed at 0." before returning 0.

> To clarify a bit my request, I am asking for feedback on the principle
> more than on the implementation right now.

My view: better exception data is good. The exception class is useful 
both to people and programs. The exception message is mainly for people 
in tracebacks for uncaught exceptions. Other attributes are mainly for 
programs that catch the exception and need more information than just 
the class. Exceptions, like SSLErrors, reporting external conditions 
that a program can respond to, are prime candidates for such attributes. 
+1 to this enhancement.

-- 
Terry Jan Reedy



More information about the Python-Dev mailing list