Added support for more options to ssl.wrap_socket

This commit is contained in:
Dariusz Suchojad 2013-09-26 19:53:56 +02:00 committed by benoitc
parent 7d10d8638f
commit 5fb61cb841
5 changed files with 144 additions and 12 deletions

View File

@ -12,6 +12,7 @@ except ImportError: # python 2.6
from . import argparse_compat as argparse
import os
import pwd
import ssl
import sys
import textwrap
import types
@ -142,12 +143,17 @@ class Config(object):
@property
def ssl_options(self):
opts = {}
if self.certfile:
opts['certfile'] = self.certfile
if self.keyfile:
opts['keyfile'] = self.keyfile
for attr in('certfile', 'keyfile', 'cert_reqs', 'ssl_version', \
'ca_certs', 'suppress_ragged_eofs', 'do_handshake_on_connect',
'ciphers'):
# suppress_ragged_eofs/do_handshake_on_connect are booleans that can
# be False hence we use hasattr instead of getattr(self, attr, None).
if hasattr(self, attr):
value = getattr(self, attr)
opts[attr] = value
return opts
@property
@ -1468,3 +1474,66 @@ class CertFile(Setting):
desc = """\
SSL certificate file
"""
class SSLVersion(Setting):
name = "ssl_version"
section = "Ssl"
cli = ["--ssl-version"]
validator = validate_pos_int
default = ssl.PROTOCOL_TLSv1
desc = """\
SSL version to use (see stdlib ssl module's)
"""
class CertReqs(Setting):
name = "cert_reqs"
section = "Ssl"
cli = ["--cert-reqs"]
validator = validate_pos_int
default = ssl.CERT_NONE
desc = """\
Whether client certificate is required (see stdlib ssl module's)
"""
class CACerts(Setting):
name = "ca_certs"
section = "Ssl"
cli = ["--ca-certs"]
meta = "FILE"
validator = validate_string
default = None
desc = """\
CA certificates file
"""
class SuppressRaggedEOFs(Setting):
name = "suppress_ragged_eofs"
section = "Ssl"
cli = ["--suppress-ragged-eofs"]
action = "store_true"
default = True
validator = validate_bool
desc = """\
Suppress ragged EOFs (see stdlib ssl module's)
"""
class DoHandshakeOnConnect(Setting):
name = "do_handshake_on_connect"
section = "Ssl"
cli = ["--do-handshake-on-connect"]
validator = validate_bool
action = "store_true"
default = False
desc = """\
Whether to perform SSL handshake on socket connect (see stdlib ssl module's)
"""
class Ciphers(Setting):
name = "ciphers"
section = "Ssl"
cli = ["--ciphers"]
validator = validate_string
default = 'TLSv1'
desc = """\
Ciphers to use (see stdlib ssl module's)
"""

View File

@ -56,8 +56,7 @@ class EventletWorker(AsyncWorker):
def handle(self, listener, client, addr):
if self.cfg.is_ssl:
client = eventlet.wrap_ssl(client, server_side=True,
do_handshake_on_connect=False,
**self.cfg.ssl_options)
**self.cfg.ssl_options)
super(EventletWorker, self).handle(listener, client, addr)

View File

@ -100,8 +100,7 @@ class GeventWorker(AsyncWorker):
ssl_args = {}
if self.cfg.is_ssl:
ssl_args = dict(server_side=True,
do_handshake_on_connect=False, **self.cfg.ssl_options)
ssl_args = dict(server_side=True, **self.cfg.ssl_options)
for s in self.sockets:
s.setblocking(1)

View File

@ -85,8 +85,7 @@ class SyncWorker(base.Worker):
try:
if self.cfg.is_ssl:
client = ssl.wrap_socket(client, server_side=True,
do_handshake_on_connect=False,
**self.cfg.ssl_options)
**self.cfg.ssl_options)
parser = http.RequestParser(self.cfg, client)
req = six.next(parser)

66
tests/test_007-ssl.py Normal file
View File

@ -0,0 +1,66 @@
# -*- coding: utf-8 -
# Copyright 2013 Dariusz Suchojad <dsuch at zato.io>
#
# This file is part of gunicorn released under the MIT license.
# See the NOTICE for more information.
# stdlib
import inspect
import ssl
from unittest import TestCase
# gunicorn
from gunicorn.config import KeyFile, CertFile, SSLVersion, CACerts, \
SuppressRaggedEOFs, DoHandshakeOnConnect, Ciphers, Setting, validate_bool, validate_string, \
validate_pos_int
class SSLTestCase(TestCase):
def test_settings_classes(self):
""" Tests all settings options and their defaults.
"""
self.assertTrue(issubclass(KeyFile, Setting))
self.assertEquals(KeyFile.name, 'keyfile')
self.assertEquals(KeyFile.section, 'Ssl')
self.assertEquals(KeyFile.cli, ['--keyfile'])
self.assertEquals(KeyFile.meta, 'FILE')
self.assertEquals(KeyFile.default, None)
self.assertTrue(issubclass(CertFile, Setting))
self.assertEquals(CertFile.name, 'certfile')
self.assertEquals(CertFile.section, 'Ssl')
self.assertEquals(CertFile.cli, ['--certfile'])
self.assertEquals(CertFile.default, None)
self.assertTrue(issubclass(SSLVersion, Setting))
self.assertEquals(SSLVersion.name, 'ssl_version')
self.assertEquals(SSLVersion.section, 'Ssl')
self.assertEquals(SSLVersion.cli, ['--ssl-version'])
self.assertEquals(SSLVersion.default, ssl.PROTOCOL_TLSv1)
self.assertTrue(issubclass(CACerts, Setting))
self.assertEquals(CACerts.name, 'ca_certs')
self.assertEquals(CACerts.section, 'Ssl')
self.assertEquals(CACerts.cli, ['--ca-certs'])
self.assertEquals(CACerts.meta, 'FILE')
self.assertEquals(CACerts.default, None)
self.assertTrue(issubclass(SuppressRaggedEOFs, Setting))
self.assertEquals(SuppressRaggedEOFs.name, 'suppress_ragged_eofs')
self.assertEquals(SuppressRaggedEOFs.section, 'Ssl')
self.assertEquals(SuppressRaggedEOFs.cli, ['--suppress-ragged-eofs'])
self.assertEquals(SuppressRaggedEOFs.action, 'store_true')
self.assertEquals(SuppressRaggedEOFs.default, True)
self.assertTrue(issubclass(DoHandshakeOnConnect, Setting))
self.assertEquals(DoHandshakeOnConnect.name, 'do_handshake_on_connect')
self.assertEquals(DoHandshakeOnConnect.section, 'Ssl')
self.assertEquals(DoHandshakeOnConnect.cli, ['--do-handshake-on-connect'])
self.assertEquals(DoHandshakeOnConnect.action, 'store_true')
self.assertEquals(DoHandshakeOnConnect.default, False)
self.assertTrue(issubclass(Ciphers, Setting))
self.assertEquals(Ciphers.name, 'ciphers')
self.assertEquals(Ciphers.section, 'Ssl')
self.assertEquals(Ciphers.cli, ['--ciphers'])
self.assertEquals(Ciphers.default, 'TLSv1')