This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: ssl.SSLSocket's keyfile argument seems to be ignored if specified without certfile
Type: behavior Stage: needs patch
Components: Library (Lib) Versions: Python 3.2
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: giampaolo.rodola Nosy List: exarkun, giampaolo.rodola, janssen, pitrou
Priority: normal Keywords:

Created on 2010-08-29 20:50 by giampaolo.rodola, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Messages (7)
msg115195 - (view) Author: Giampaolo Rodola' (giampaolo.rodola) * (Python committer) Date: 2010-08-29 20:50
By taking a look at ssl.py it seems that keyfile argument is ignored if certfile argument is not specified as well.
Here's an extract of ssl.py code:

class SSLSocket:

    def __init__(self, sock=None, keyfile=None, certfile=None,
                 server_side=False, cert_reqs=CERT_NONE,
                 ssl_version=PROTOCOL_SSLv23, ca_certs=None,
                 do_handshake_on_connect=True,
                 family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None,
                 suppress_ragged_eofs=True, ciphers=None,
                 _context=None):
        [...]
            if certfile and not keyfile:
                keyfile = certfile
        [...]
            if certfile:
                self.context.load_cert_chain(certfile, keyfile)

So at the current stage this:

>>> ssl.wrap_socket(socket.socket(), keyfile="XXX")
<ssl.SSLSocket object, fd=5, family=2, type=1, proto=0>

...would be equal to:

>>> ssl.wrap_socket(socket.socket())
<ssl.SSLSocket object, fd=5, family=2, type=1, proto=0>


To me this leads to one question: are there circumstances in which it makes sense to specify "keyfile" and *not* "certfile"?
As far as I know, on server-side it is always required to specify *at least* certfile argument, in which case this would represent a bug.
Not sure about client-side sockets.
msg115221 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2010-08-30 15:05
Good catch. keyfile without certfile should be forbidden, and raise a ValueError.
msg115222 - (view) Author: Giampaolo Rodola' (giampaolo.rodola) * (Python committer) Date: 2010-08-30 15:18
Are we sure? Do we have a reference which states that?
msg115223 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2010-08-30 15:22
Not really, but in previous versions it would fail as soon as you try to connect:

>>> s = ssl.wrap_socket(socket.socket(), keyfile="XXX")
>>> s.connect(("svn.python.org", 443))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/antoine/cpython/27/Lib/ssl.py", line 295, in connect
    self.ca_certs, self.ciphers)
ssl.SSLError: _ssl.c:289: Both the key & certificate files must be specified

It's better to catch the problem up-front, though. As for whether SSLError or ValueError should be preferred, I think ValueError is cleaner (it's really a bad use of the API).
msg115236 - (view) Author: Giampaolo Rodola' (giampaolo.rodola) * (Python committer) Date: 2010-08-30 18:29
Fixed in r84370.
msg115303 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2010-09-01 14:44
I'm not sure which commit it is, but test_ssl has started failing on some buildbots:

======================================================================
ERROR: test_errors (test.test_ssl.BasicSocketTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/srv/buildbot/buildarea/3.x.bolen-ubuntu/build/Lib/test/test_ssl.py", line 186, in test_errors
    s = ssl.wrap_socket(sock, server_side=True, certfile=CERTFILE)
  File "/srv/buildbot/buildarea/3.x.bolen-ubuntu/build/Lib/ssl.py", line 414, in wrap_socket
    ciphers=ciphers)
  File "/srv/buildbot/buildarea/3.x.bolen-ubuntu/build/Lib/ssl.py", line 137, in __init__
    self.context.load_cert_chain(certfile, keyfile)
ssl.SSLError: [Errno 185057381] _ssl.c:1609: error:0B07C065:x509 certificate routines:X509_STORE_add_cert:cert already in hash table

======================================================================
ERROR: test_protocol_sslv2 (test.test_ssl.ThreadedTests)
Connecting to an SSLv2 server with various client options
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/srv/buildbot/buildarea/3.x.bolen-ubuntu/build/Lib/test/test_ssl.py", line 80, in f
    return func(*args, **kwargs)
  File "/srv/buildbot/buildarea/3.x.bolen-ubuntu/build/Lib/test/test_ssl.py", line 1100, in test_protocol_sslv2
    try_protocol_combo(ssl.PROTOCOL_SSLv2, ssl.PROTOCOL_SSLv2, True)
  File "/srv/buildbot/buildarea/3.x.bolen-ubuntu/build/Lib/test/test_ssl.py", line 969, in try_protocol_combo
    ctx.load_cert_chain(CERTFILE)
ssl.SSLError: [Errno 336445442] _ssl.c:1609: error:140DC002:SSL routines:SSL_CTX_use_certificate_chain_file:system lib

See e.g. http://www.python.org/dev/buildbot/builders/x86%20Ubuntu%203.x/builds/1870
msg115306 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2010-09-01 14:50
Actually, it started failing exactly after r84352 (issue #9706).
History
Date User Action Args
2022-04-11 14:57:05adminsetgithub: 53920
2010-09-01 14:50:55pitrousetstatus: open -> closed

messages: + msg115306
2010-09-01 14:44:30pitrousetstatus: closed -> open
assignee: giampaolo.rodola
messages: + msg115303
2010-08-30 18:29:13giampaolo.rodolasetstatus: open -> closed
resolution: fixed
messages: + msg115236
2010-08-30 15:22:54pitrousetmessages: + msg115223
2010-08-30 15:18:12giampaolo.rodolasetmessages: + msg115222
2010-08-30 15:05:07pitrousetversions: + Python 3.2
messages: + msg115221

components: + Library (Lib)
type: behavior
stage: needs patch
2010-08-29 20:50:02giampaolo.rodolacreate