Index: Doc/library/ssl.rst =================================================================== --- Doc/library/ssl.rst (revision 77450) +++ Doc/library/ssl.rst (working copy) @@ -50,7 +50,7 @@ is a subtype of :exc:`socket.error`, which in turn is a subtype of :exc:`IOError`. -.. function:: wrap_socket (sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ssl_version={see docs}, ca_certs=None, do_handshake_on_connect=True, suppress_ragged_eofs=True) +.. function:: wrap_socket (sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ssl_version={see docs}, ca_certs=None, do_handshake_on_connect=True, suppress_ragged_eofs=True, ssl_options=0) Takes an instance ``sock`` of :class:`socket.socket`, and returns an instance of :class:`ssl.SSLSocket`, a subtype of :class:`socket.socket`, which wraps @@ -135,6 +135,11 @@ normal EOF in response to unexpected EOF errors raised from the underlying socket; if :const:`False`, it will raise the exceptions back to the caller. + The parameter ``ssl_options`` specifies various options related to the + functioning of the SSL protocol. Enables bug compatibility with other SSL + implementations. It is an or'ing of the three values :const:`OP_NO_SSLv2`, + :const:`OP_NO_SSLv3`, or :const:`OP_NO_TLSv1`. + .. function:: RAND_status() Returns True if the SSL pseudo-random number generator has been seeded with @@ -240,7 +245,22 @@ modern version, and probably the best choice for maximum protection, if both sides can speak it. +.. data:: OP_NO_SSLv2 + Prevents an SSLv2 connection. This option is only applicable when connecting + with SSLv23. It prevents the peers choosing SSLv2 as the protocol version. + +.. data:: OP_NO_SSLv3 + + Prevents an SSLv3 connection. This option is only applicable when connecting + with SSLv23. It prevents the peers choosing SSLv3 as the protocol version. + +.. data:: OP_NO_TLSv1 + + Prevents a Transport Layer Security (TLS) v1 connection. This option is only + applicable when connecting with SSLv23. It prevents the peers choosing TLSv1 + as the protocol version. + SSLSocket Objects ----------------- Index: Lib/ssl.py =================================================================== --- Lib/ssl.py (revision 77450) +++ Lib/ssl.py (working copy) @@ -62,6 +62,7 @@ from _ssl import SSLError from _ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED from _ssl import PROTOCOL_SSLv2, PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1 +from _ssl import OP_NO_SSLv2, OP_NO_SSLv3, OP_NO_TLSv1 from _ssl import RAND_status, RAND_egd, RAND_add from _ssl import \ SSL_ERROR_ZERO_RETURN, \ @@ -88,7 +89,7 @@ server_side=False, cert_reqs=CERT_NONE, ssl_version=PROTOCOL_SSLv23, ca_certs=None, do_handshake_on_connect=True, - suppress_ragged_eofs=True): + suppress_ragged_eofs=True, ssl_options=0): socket.__init__(self, _sock=sock._sock) # the initializer for socket trashes the methods (tsk, tsk), so... self.send = lambda data, flags=0: SSLSocket.send(self, data, flags) @@ -110,7 +111,8 @@ # yes, create the SSL object self._sslobj = _ssl.sslwrap(self._sock, server_side, keyfile, certfile, - cert_reqs, ssl_version, ca_certs) + cert_reqs, ssl_version, ca_certs, + ssl_options) if do_handshake_on_connect: timeout = self.gettimeout() try: @@ -125,6 +127,7 @@ self.ca_certs = ca_certs self.do_handshake_on_connect = do_handshake_on_connect self.suppress_ragged_eofs = suppress_ragged_eofs + self.ssl_options = ssl_options self._makefile_refs = 0 def read(self, len=1024): @@ -304,7 +307,7 @@ socket.connect(self, addr) self._sslobj = _ssl.sslwrap(self._sock, False, self.keyfile, self.certfile, self.cert_reqs, self.ssl_version, - self.ca_certs) + self.ca_certs, self.ssl_options) if self.do_handshake_on_connect: self.do_handshake() @@ -323,7 +326,8 @@ ssl_version=self.ssl_version, ca_certs=self.ca_certs, do_handshake_on_connect=self.do_handshake_on_connect, - suppress_ragged_eofs=self.suppress_ragged_eofs), + suppress_ragged_eofs=self.suppress_ragged_eofs, + ssl_options=self.ssl_options), addr) def makefile(self, mode='r', bufsize=-1): @@ -341,13 +345,14 @@ server_side=False, cert_reqs=CERT_NONE, ssl_version=PROTOCOL_SSLv23, ca_certs=None, do_handshake_on_connect=True, - suppress_ragged_eofs=True): + suppress_ragged_eofs=True, ssl_options=0): return SSLSocket(sock, keyfile=keyfile, certfile=certfile, server_side=server_side, cert_reqs=cert_reqs, ssl_version=ssl_version, ca_certs=ca_certs, do_handshake_on_connect=do_handshake_on_connect, - suppress_ragged_eofs=suppress_ragged_eofs) + suppress_ragged_eofs=suppress_ragged_eofs, + ssl_options=ssl_options) # some utility functions Index: Modules/_ssl.c =================================================================== --- Modules/_ssl.c (revision 77450) +++ Modules/_ssl.c (working copy) @@ -261,7 +261,7 @@ enum py_ssl_server_or_client socket_type, enum py_ssl_cert_requirements certreq, enum py_ssl_version proto_version, - char *cacerts_file) + char *cacerts_file, int options) { PySSLObject *self; char *errstr = NULL; @@ -355,7 +355,8 @@ } /* ssl compatibility */ - SSL_CTX_set_options(self->ctx, SSL_OP_ALL); + options |= SSL_OP_ALL; + SSL_CTX_set_options(self->ctx, options); verification_mode = SSL_VERIFY_NONE; if (certreq == PY_SSL_CERT_OPTIONAL) @@ -404,35 +405,36 @@ int server_side = 0; int verification_mode = PY_SSL_CERT_NONE; int protocol = PY_SSL_VERSION_SSL23; + int options = 0; char *key_file = NULL; char *cert_file = NULL; char *cacerts_file = NULL; - if (!PyArg_ParseTuple(args, "O!i|zziiz:sslwrap", + if (!PyArg_ParseTuple(args, "O!i|zziizi:sslwrap", PySocketModule.Sock_Type, &Sock, &server_side, &key_file, &cert_file, &verification_mode, &protocol, - &cacerts_file)) + &cacerts_file, &options)) return NULL; /* fprintf(stderr, "server_side is %d, keyfile %p, certfile %p, verify_mode %d, " - "protocol %d, certs %p\n", + "protocol %d, certs %p, options %d\n", server_side, key_file, cert_file, verification_mode, - protocol, cacerts_file); + protocol, cacerts_file, options); */ return (PyObject *) newPySSLObject(Sock, key_file, cert_file, server_side, verification_mode, - protocol, cacerts_file); + protocol, cacerts_file, options); } PyDoc_STRVAR(ssl_doc, "sslwrap(socket, server_side, [keyfile, certfile, certs_mode, protocol,\n" -" cacertsfile]) -> sslobject"); +" cacertsfile, options]) -> sslobject"); /* SSL object methods */ @@ -1640,4 +1642,9 @@ PY_SSL_VERSION_SSL23); PyModule_AddIntConstant(m, "PROTOCOL_TLSv1", PY_SSL_VERSION_TLS1); + + /* protocol options */ + PyModule_AddIntConstant(m, "OP_NO_SSLv2", SSL_OP_NO_SSLv2); + PyModule_AddIntConstant(m, "OP_NO_SSLv3", SSL_OP_NO_SSLv3); + PyModule_AddIntConstant(m, "OP_NO_TLSv1", SSL_OP_NO_TLSv1); }