diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2010-10-22 18:19:07 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2010-10-22 18:19:07 (GMT) |
commit | d532321f7ba2e23e4110f05331fee8beca736826 (patch) | |
tree | 9383fb529fee0b92edc2a06e0435b7e8560cb1ec /Modules | |
parent | 4ebfdf01bb128005842be322fc89457d527ff000 (diff) | |
download | cpython-d532321f7ba2e23e4110f05331fee8beca736826.zip cpython-d532321f7ba2e23e4110f05331fee8beca736826.tar.gz cpython-d532321f7ba2e23e4110f05331fee8beca736826.tar.bz2 |
Issue #5639: Add a *server_hostname* argument to `SSLContext.wrap_socket`
in order to support the TLS SNI extension. `HTTPSConnection` and
`urlopen()` also use this argument, so that HTTPS virtual hosts are now
supported.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_ssl.c | 45 |
1 files changed, 40 insertions, 5 deletions
diff --git a/Modules/_ssl.c b/Modules/_ssl.c index e1cd3dc..6fa65b2 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -281,7 +281,8 @@ _setSSLError (char *errstr, int errcode, char *filename, int lineno) { static PySSLSocket * newPySSLSocket(SSL_CTX *ctx, PySocketSockObject *sock, - enum py_ssl_server_or_client socket_type) + enum py_ssl_server_or_client socket_type, + char *server_hostname) { PySSLSocket *self; @@ -305,6 +306,11 @@ newPySSLSocket(SSL_CTX *ctx, PySocketSockObject *sock, SSL_set_mode(self->ssl, SSL_MODE_AUTO_RETRY); #endif +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + if (server_hostname != NULL) + SSL_set_tlsext_host_name(self->ssl, server_hostname); +#endif + /* If the socket is in non-blocking mode or timeout mode, set the BIO * to non-blocking mode (blocking is the default) */ @@ -1711,16 +1717,37 @@ load_verify_locations(PySSLContext *self, PyObject *args, PyObject *kwds) static PyObject * context_wrap_socket(PySSLContext *self, PyObject *args, PyObject *kwds) { - char *kwlist[] = {"sock", "server_side", NULL}; + char *kwlist[] = {"sock", "server_side", "server_hostname", NULL}; PySocketSockObject *sock; int server_side = 0; + char *hostname = NULL; + PyObject *hostname_obj, *res; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!i:_wrap_socket", kwlist, + /* server_hostname is either None (or absent), or to be encoded + using the idna encoding. */ + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!i|O!:_wrap_socket", kwlist, PySocketModule.Sock_Type, - &sock, &server_side)) + &sock, &server_side, + Py_TYPE(Py_None), &hostname_obj)) { + PyErr_Clear(); + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!iet:_wrap_socket", kwlist, + PySocketModule.Sock_Type, + &sock, &server_side, + "idna", &hostname)) + return NULL; +#ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME + PyMem_Free(hostname); + PyErr_SetString(PyExc_ValueError, "server_hostname is not supported " + "by your OpenSSL library"); return NULL; +#endif + } - return (PyObject *) newPySSLSocket(self->ctx, sock, server_side); + res = (PyObject *) newPySSLSocket(self->ctx, sock, server_side, + hostname); + if (hostname != NULL) + PyMem_Free(hostname); + return res; } static PyObject * @@ -2090,6 +2117,14 @@ PyInit__ssl(void) PyModule_AddIntConstant(m, "OP_NO_SSLv3", SSL_OP_NO_SSLv3); PyModule_AddIntConstant(m, "OP_NO_TLSv1", SSL_OP_NO_TLSv1); +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME + r = Py_True; +#else + r = Py_False; +#endif + Py_INCREF(r); + PyModule_AddObject(m, "HAS_SNI", r); + /* OpenSSL version */ /* SSLeay() gives us the version of the library linked against, which could be different from the headers version. |