New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for client certificate verification in SSLAdapter (patch included) #1001

Closed
bb-migration opened this Issue Apr 12, 2010 · 24 comments

Comments

Projects
None yet
6 participants
@bb-migration

bb-migration commented Apr 12, 2010

Originally reported by: Anonymous


Enhancement

Adding support for client SSL certificate verification to wsgiserver's SSLAdapter

Reason

SSL support is critical for modern webservers to provide secure services to users.
However, there are times when applications running behind the webservers
need to determine which clients are actually communicating them. While HTTP
basic_auth can provide authentication, SSL provides another means to verify
client identity: client certification verification.

Similar to the server providing its SSL certificate, when client verification is in use,
clients must provide a certificate signed by a CA that the server recognizes in order
for the client to be allowed to connect.

Changes

This patch adds another optional keyword argument to the SSLAdapter __init__() called
''client_CA''. ''client_CA'' is a string that contains a path to a CA certificate. When client_CA
is present, the SSLAdapter knows to perform client verification using this CA. When
absent, SSLAdapter behaves as before, ie with no client verification.

Bugs/Issues

While verification is performed correctly for both the ssl_pyopenssl SSLAdapter and the
ssl_builtin SSLAdapter, the different implementations provide varying levels of support
for SSL client environment variables that are traditionally provided by Apache's mod_ssl.
See this page for details Mod_SSL Environment Variables.

ssl_pyopenssl currently provides '''no''' client environment variables due to the fact that the
SSL handshake and thus the access to the client's certificate occurs at first data transfer -
well after the environment variables are set by the SSLAdapter wrap() function.

ssl_builtin provides minimal environment variables. The major limiting factor is that
python's builtin ssl routines only expose a small amount of information about the
certificates, and then only for the client certificate. This problem will be difficult to fix
if ssl_builtin must depend solely on python's ssl.

Patch

See attached Diff

Reported by nmitchell@anl.gov


@bb-migration

This comment has been minimized.

Show comment
Hide comment
@bb-migration

bb-migration Sep 24, 2010

Original comment by Anonymous:


I ran into a problem with this patch in the tick() method of the HTTPServer class in wsgiserver/__init__.py

The HTTPServer class has a list of socket errors which it "ignores", meaning that these errors do not cause the entire server to shut down. Any other type of socket error causes CherryPy to exit, because the server believes that something has gone wrong with the socket it uses to accept incoming connections. It uses the global "socket_errors_to_ignore" list to track these recoverable errors.

If a client connects with no certificate or a bad certificate when using the builtin ssl module, then an ssl.SSLError exception is raised. This is a subclass of socket.error, with an error number value of 1, which is EPERM. Unfortunately, EPERM is not currently on the socket_errors_to_ignore list, so a single bad client can cause the entire server to exit.

I've added EPERM to this list and submitted an updated patch.

bb-migration commented Sep 24, 2010

Original comment by Anonymous:


I ran into a problem with this patch in the tick() method of the HTTPServer class in wsgiserver/__init__.py

The HTTPServer class has a list of socket errors which it "ignores", meaning that these errors do not cause the entire server to shut down. Any other type of socket error causes CherryPy to exit, because the server believes that something has gone wrong with the socket it uses to accept incoming connections. It uses the global "socket_errors_to_ignore" list to track these recoverable errors.

If a client connects with no certificate or a bad certificate when using the builtin ssl module, then an ssl.SSLError exception is raised. This is a subclass of socket.error, with an error number value of 1, which is EPERM. Unfortunately, EPERM is not currently on the socket_errors_to_ignore list, so a single bad client can cause the entire server to exit.

I've added EPERM to this list and submitted an updated patch.

@bb-migration

This comment has been minimized.

Show comment
Hide comment
@bb-migration

bb-migration Oct 5, 2010

Original comment by Anonymous:


I've extended the improvements further, mostly by adding hostname checking to both the "builtin" and "pyopenssl" adapters. I also added a few more checks for edge cases, such as an "except TypeError" catch for http://bugs.python.org/issue9729

My currently project really needs client certificate checking to be configurable, so I added "server.ssl_client_CA" and "server.ssl_client_check" options. The "ssl_client_CA" is exactly what it sounds like, and "ssl_client_check" must be one of "ignore", "optional", or "required" (and is "ignore" by default). These settings cause client certificate checking to use the following options in the "builtin" and "pyopenssl" adapters, respectively:

  • "ignore" denotes either ssl.CERT_NONE or OpenSSL.SSL.VERIFY_NONE
  • "optional" denotes either ssl.CERT_OPTIONAL or OpenSSL.SSL.VERIFY_PEER
  • "required" denotes either ssl.CERT_REQUIRED or OpenSSL.SSL.VERIFY_PEER | OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT

Because these configuration options introduce a lot of combinations of settings, I've also attached a test_ssl.py file with some helper files in the same directory which contain 50 TestCase subclasses, each with 2 tests for clients with and without certificates. Each TestCase checks a different combination of settings, so that every possible combination is covered.

For example, there's a TestCase for the following case:

  • server has a valid certificate
  • client has a certificate signed properly by the CA, but with the wrong hostname
  • server is using the pyopenssl module
  • server has its "server.ssl_client_check" option set to "optional"

This TestCase would verify that a client connecting without a certificate would succeed, while the client connecting with the wrong-hostname certificate would fail.

If anyone has any questions about this ticket, feel free to email me. Also let me know if there's anything else I can add which would make it more likely for the ticket to get accepted. I'd especially like to know if there's anything I can do to get this ticket accepted before the CherryPy 3.2.0 release, though I imagine that's unlikely since a release candidate has already been put together.

bb-migration commented Oct 5, 2010

Original comment by Anonymous:


I've extended the improvements further, mostly by adding hostname checking to both the "builtin" and "pyopenssl" adapters. I also added a few more checks for edge cases, such as an "except TypeError" catch for http://bugs.python.org/issue9729

My currently project really needs client certificate checking to be configurable, so I added "server.ssl_client_CA" and "server.ssl_client_check" options. The "ssl_client_CA" is exactly what it sounds like, and "ssl_client_check" must be one of "ignore", "optional", or "required" (and is "ignore" by default). These settings cause client certificate checking to use the following options in the "builtin" and "pyopenssl" adapters, respectively:

  • "ignore" denotes either ssl.CERT_NONE or OpenSSL.SSL.VERIFY_NONE
  • "optional" denotes either ssl.CERT_OPTIONAL or OpenSSL.SSL.VERIFY_PEER
  • "required" denotes either ssl.CERT_REQUIRED or OpenSSL.SSL.VERIFY_PEER | OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT

Because these configuration options introduce a lot of combinations of settings, I've also attached a test_ssl.py file with some helper files in the same directory which contain 50 TestCase subclasses, each with 2 tests for clients with and without certificates. Each TestCase checks a different combination of settings, so that every possible combination is covered.

For example, there's a TestCase for the following case:

  • server has a valid certificate
  • client has a certificate signed properly by the CA, but with the wrong hostname
  • server is using the pyopenssl module
  • server has its "server.ssl_client_check" option set to "optional"

This TestCase would verify that a client connecting without a certificate would succeed, while the client connecting with the wrong-hostname certificate would fail.

If anyone has any questions about this ticket, feel free to email me. Also let me know if there's anything else I can add which would make it more likely for the ticket to get accepted. I'd especially like to know if there's anything I can do to get this ticket accepted before the CherryPy 3.2.0 release, though I imagine that's unlikely since a release candidate has already been put together.

@bb-migration

This comment has been minimized.

Show comment
Hide comment
@bb-migration

bb-migration Oct 8, 2010

Original comment by Anonymous:


I've improved client certificate checking in the following ways:

  • wildcard hostnames (e.g. *.example.com) are now supported
  • IP addresses in the common name field are handled appropriately
  • hostname checking can be turned on and off by the server.ssl_client_check_host config option

I did this because it turns out that my project needs to be able to support client certificates both with and without hostname checking. I'll upload the patch after posting this comment.

I also added a lot more unit tests, so we're testing every possible combination of settings with a total of 460 unit tests in cherrypy/tests/test_ssl.py, e.g.

  • all tests are run for both the "builtin" and "pyopenssl" adapters
  • all combinations of configuration settings
  • connections are tested for connections both with and without client certificates to ensure that the connection either succeeds or fails appropriately
  • server binding to "localhost", "127.0.0.1", and "0.0.0.0" (this matters because it affects the client's certificate validation, which affects the server's error handling for failed connections)
  • client connecting to either "localhost" "127.0.0.1" (this REALLY matters, because it affects what address the server gets when calling sock.getpeername())
  • client certificates signed to "localhost", "127.0.0.1", and "*.localhost"
  • bad client and server certificates (e.g. wrong hostname, signed by the wrong CA, etc), making sure that failures happen when expected but that they don't bring down the entire server

Anyway, I don't know if my design will be considered acceptable, but at least the implementation is thoroughly tested. Again, if there's anything I can do to help this patch get accepted into the trunk, just let me know.

bb-migration commented Oct 8, 2010

Original comment by Anonymous:


I've improved client certificate checking in the following ways:

  • wildcard hostnames (e.g. *.example.com) are now supported
  • IP addresses in the common name field are handled appropriately
  • hostname checking can be turned on and off by the server.ssl_client_check_host config option

I did this because it turns out that my project needs to be able to support client certificates both with and without hostname checking. I'll upload the patch after posting this comment.

I also added a lot more unit tests, so we're testing every possible combination of settings with a total of 460 unit tests in cherrypy/tests/test_ssl.py, e.g.

  • all tests are run for both the "builtin" and "pyopenssl" adapters
  • all combinations of configuration settings
  • connections are tested for connections both with and without client certificates to ensure that the connection either succeeds or fails appropriately
  • server binding to "localhost", "127.0.0.1", and "0.0.0.0" (this matters because it affects the client's certificate validation, which affects the server's error handling for failed connections)
  • client connecting to either "localhost" "127.0.0.1" (this REALLY matters, because it affects what address the server gets when calling sock.getpeername())
  • client certificates signed to "localhost", "127.0.0.1", and "*.localhost"
  • bad client and server certificates (e.g. wrong hostname, signed by the wrong CA, etc), making sure that failures happen when expected but that they don't bring down the entire server

Anyway, I don't know if my design will be considered acceptable, but at least the implementation is thoroughly tested. Again, if there's anything I can do to help this patch get accepted into the trunk, just let me know.

@bb-migration

This comment has been minimized.

Show comment
Hide comment
@bb-migration

bb-migration Oct 12, 2010

Original comment by Anonymous:


Apologies for the incorrect attachment summary; that was a bad autocomplete.

The latest patch includes a sensible check in our test_ssl.py unit tests for whether "localhost" is an IPv4 or IPv6 address, since this affects whether it's worth trying to connect to the server at "127.0.0.1", which we want to do if possible to test all possible ways to for certificate checks to succeed or fail.

The actual wsgiserver code is unchanged in this latest patch (v5) compared to the previous version (v4).

bb-migration commented Oct 12, 2010

Original comment by Anonymous:


Apologies for the incorrect attachment summary; that was a bad autocomplete.

The latest patch includes a sensible check in our test_ssl.py unit tests for whether "localhost" is an IPv4 or IPv6 address, since this affects whether it's worth trying to connect to the server at "127.0.0.1", which we want to do if possible to test all possible ways to for certificate checks to succeed or fail.

The actual wsgiserver code is unchanged in this latest patch (v5) compared to the previous version (v4).

@bb-migration

This comment has been minimized.

Show comment
Hide comment
@bb-migration

bb-migration Oct 13, 2010

Original comment by Anonymous:


Would it be possible to get client enviroment variable information from pyopenssl,
if we would do the handshake explictly?
There is a function in pyopenssl to do the handshake...
Could it be added to wrap() ?

bb-migration commented Oct 13, 2010

Original comment by Anonymous:


Would it be possible to get client enviroment variable information from pyopenssl,
if we would do the handshake explictly?
There is a function in pyopenssl to do the handshake...
Could it be added to wrap() ?

@bb-migration

This comment has been minimized.

Show comment
Hide comment
@bb-migration

bb-migration Jul 19, 2012

Original comment by Chris St. Pierre (Bitbucket: stpierre, GitHub: stpierre):


I've updated the latest patch and submitted a pull request: https://bitbucket.org/cherrypy/cherrypy/pull-request/12/added-support-for-client-certificate

bb-migration commented Jul 19, 2012

Original comment by Chris St. Pierre (Bitbucket: stpierre, GitHub: stpierre):


I've updated the latest patch and submitted a pull request: https://bitbucket.org/cherrypy/cherrypy/pull-request/12/added-support-for-client-certificate

@bb-migration

This comment has been minimized.

Show comment
Hide comment
@bb-migration

bb-migration Sep 19, 2012

Original comment by Michael Walsh (Bitbucket: nemonik, GitHub: nemonik):


The pull requests source repo appears to have been deleted. What is the status of this ticket? Does a patch exist? Has the patch been accepted, if so where?

bb-migration commented Sep 19, 2012

Original comment by Michael Walsh (Bitbucket: nemonik, GitHub: nemonik):


The pull requests source repo appears to have been deleted. What is the status of this ticket? Does a patch exist? Has the patch been accepted, if so where?

@bb-migration

This comment has been minimized.

Show comment
Hide comment
@bb-migration

bb-migration Sep 20, 2012

Original comment by Chris St. Pierre (Bitbucket: stpierre, GitHub: stpierre):


Sorry, that's my fault -- still quite new to Hg, and it scares and confuses me at times. The patch in the ticket applied fairly cleanly and passed tests without any modifications -- I just opened a pull request to hopefully speed the process along, since this ticket was fairly old. If you want me to open another pull request I can do that.

bb-migration commented Sep 20, 2012

Original comment by Chris St. Pierre (Bitbucket: stpierre, GitHub: stpierre):


Sorry, that's my fault -- still quite new to Hg, and it scares and confuses me at times. The patch in the ticket applied fairly cleanly and passed tests without any modifications -- I just opened a pull request to hopefully speed the process along, since this ticket was fairly old. If you want me to open another pull request I can do that.

@bb-migration

This comment has been minimized.

Show comment
Hide comment
@bb-migration

bb-migration Sep 27, 2012

Original comment by Michael Walsh (Bitbucket: nemonik, GitHub: nemonik):


I'll try the patch. If you can open another pull request that would be great. I'd really appreciate it. I plan to use this for an example with my rules engine for to create an example for an article I am writing. I tried Twisted, but what should work hasn't been working for me.

bb-migration commented Sep 27, 2012

Original comment by Michael Walsh (Bitbucket: nemonik, GitHub: nemonik):


I'll try the patch. If you can open another pull request that would be great. I'd really appreciate it. I plan to use this for an example with my rules engine for to create an example for an article I am writing. I tried Twisted, but what should work hasn't been working for me.

@bb-migration

This comment has been minimized.

Show comment
Hide comment
@bb-migration

bb-migration Sep 27, 2012

Original comment by Michael Walsh (Bitbucket: nemonik, GitHub: nemonik):


The v5 of the patch fails at cherrypy/wsgiserver/init.py at line 861. Hmm. There has been some changes on this file since you created the patch.

bb-migration commented Sep 27, 2012

Original comment by Michael Walsh (Bitbucket: nemonik, GitHub: nemonik):


The v5 of the patch fails at cherrypy/wsgiserver/init.py at line 861. Hmm. There has been some changes on this file since you created the patch.

@bb-migration

This comment has been minimized.

Show comment
Hide comment
@bb-migration

bb-migration Sep 28, 2012

Original comment by Chris St. Pierre (Bitbucket: stpierre, GitHub: stpierre):


New pull request submitted: https://bitbucket.org/cherrypy/cherrypy/pull-request/15/added-support-for-client-certificate

bb-migration commented Sep 28, 2012

Original comment by Chris St. Pierre (Bitbucket: stpierre, GitHub: stpierre):


New pull request submitted: https://bitbucket.org/cherrypy/cherrypy/pull-request/15/added-support-for-client-certificate

@bb-migration

This comment has been minimized.

Show comment
Hide comment
@bb-migration

bb-migration May 2, 2013

Original comment by depassp (Bitbucket: depassp, GitHub: depassp):


I'd really like this functionality!

bb-migration commented May 2, 2013

Original comment by depassp (Bitbucket: depassp, GitHub: depassp):


I'd really like this functionality!

@bb-migration

This comment has been minimized.

Show comment
Hide comment
@bb-migration

bb-migration Dec 3, 2013

Original comment by Tim Chase (Bitbucket: gumnos, GitHub: gumnos):


Is there a way to access the client-cert from within a request response? Something like

@cherrypy.expose
def hello(self):
    return repr(magic().getpeercert())

making use of getpeercert()

bb-migration commented Dec 3, 2013

Original comment by Tim Chase (Bitbucket: gumnos, GitHub: gumnos):


Is there a way to access the client-cert from within a request response? Something like

@cherrypy.expose
def hello(self):
    return repr(magic().getpeercert())

making use of getpeercert()

@bb-migration

This comment has been minimized.

Show comment
Hide comment
@bb-migration

bb-migration Mar 20, 2014

Original comment by Nathan Kinder (Bitbucket: nkinder, GitHub: nkinder):


I'm working on updating the patch for this issue. Aside from rebasing, I found that some minor changes are needed in the new tests to clear out the SSL adapter to prevent later tests from failing. I should have a new pull request ready for this soon.

bb-migration commented Mar 20, 2014

Original comment by Nathan Kinder (Bitbucket: nkinder, GitHub: nkinder):


I'm working on updating the patch for this issue. Aside from rebasing, I found that some minor changes are needed in the new tests to clear out the SSL adapter to prevent later tests from failing. I should have a new pull request ready for this soon.

@bb-migration

This comment has been minimized.

Show comment
Hide comment
@bb-migration

bb-migration Oct 2, 2015

Original comment by Anthony Nwokafor (Bitbucket: junnytony, GitHub: Unknown):


Hi guys, any update on this issue? It would be great to have this functionality in cherrypy!

bb-migration commented Oct 2, 2015

Original comment by Anthony Nwokafor (Bitbucket: junnytony, GitHub: Unknown):


Hi guys, any update on this issue? It would be great to have this functionality in cherrypy!

@bb-migration

This comment has been minimized.

Show comment
Hide comment
@bb-migration

bb-migration Nov 13, 2015

Original comment by james_puderer (Bitbucket: james_puderer, GitHub: Unknown):


Please resuscitate.

bb-migration commented Nov 13, 2015

Original comment by james_puderer (Bitbucket: james_puderer, GitHub: Unknown):


Please resuscitate.

@bb-migration

This comment has been minimized.

Show comment
Hide comment
@bb-migration

bb-migration Apr 27, 2016

Original comment by Joseph Tate (Bitbucket: josephtate, GitHub: josephtate):


There were problems running the test suite on the pull request. I'd previously merged it, but I had to back it out because the tests were failing. At this point we'll need a new pull request.

bb-migration commented Apr 27, 2016

Original comment by Joseph Tate (Bitbucket: josephtate, GitHub: josephtate):


There were problems running the test suite on the pull request. I'd previously merged it, but I had to back it out because the tests were failing. At this point we'll need a new pull request.

@dpeschman

This comment has been minimized.

Show comment
Hide comment
@dpeschman

dpeschman Oct 7, 2017

Was this ever merged? @josephtate

dpeschman commented Oct 7, 2017

Was this ever merged? @josephtate

@josephtate

This comment has been minimized.

Show comment
Hide comment
@josephtate

josephtate Oct 7, 2017

Contributor
Contributor

josephtate commented Oct 7, 2017

@webknjaz

This comment has been minimized.

Show comment
Hide comment
@webknjaz

webknjaz Oct 8, 2017

Member

@josephtate @jaraco is it possible to restore it from bitbucket?

Member

webknjaz commented Oct 8, 2017

@josephtate @jaraco is it possible to restore it from bitbucket?

@jaraco

This comment has been minimized.

Show comment
Hide comment
@jaraco

jaraco Oct 30, 2017

Member

The code was merged in 1eb0b94 and backed out in a89e31f.

Member

jaraco commented Oct 30, 2017

The code was merged in 1eb0b94 and backed out in a89e31f.

@GP-S

This comment has been minimized.

Show comment
Hide comment
@GP-S

GP-S Aug 29, 2018

Hello guys! I was just wondering if this issue is still actual ?

GP-S commented Aug 29, 2018

Hello guys! I was just wondering if this issue is still actual ?

@webknjaz

This comment has been minimized.

Show comment
Hide comment
@webknjaz

webknjaz Aug 29, 2018

Member

@GP-S It looks like that patch has been reverted because of some issues. But it should be possible to modify context attribute of SSL Adapter you use upon initialization to have client verification enabled.

@jaraco might know more.

Member

webknjaz commented Aug 29, 2018

@GP-S It looks like that patch has been reverted because of some issues. But it should be possible to modify context attribute of SSL Adapter you use upon initialization to have client verification enabled.

@jaraco might know more.

@jaraco

This comment has been minimized.

Show comment
Hide comment
@jaraco

jaraco Aug 29, 2018

Member

I don't think there's much that can be done to revive the work that was attempted before. The project has since (a) consolidated wsgiserver2/3 modules and (b) extracted the wsgiserver functionality into cheroot. All of this refactoring means that the functionality that was created in those prior commits is largely unusable except as a reference.

I do see the reference to cherrypy/cheroot#52, which I believe re-implements this functionality in the newer codebase. It looks like maybe that PR was abandoned and is probably the best place to resume this activity.

Member

jaraco commented Aug 29, 2018

I don't think there's much that can be done to revive the work that was attempted before. The project has since (a) consolidated wsgiserver2/3 modules and (b) extracted the wsgiserver functionality into cheroot. All of this refactoring means that the functionality that was created in those prior commits is largely unusable except as a reference.

I do see the reference to cherrypy/cheroot#52, which I believe re-implements this functionality in the newer codebase. It looks like maybe that PR was abandoned and is probably the best place to resume this activity.

clrpackages pushed a commit to clearlinux-pkgs/cheroot that referenced this issue Sep 3, 2018

[update to 6.5.1] Add workaround for build failures on Python 3.7 (ya…
…ml/pyyaml#126).

Dan Peschman (1):
      Pass client certificate fields to WSGI environment; unit test HTTPS

Jason R. Coombs (36):
      reference the license file in metadata
      Use https
      Add build-docs env in tox.
      Run only default environment by default.
      To support namespace packages, Setuptools must be 31.0.1. This change is necessary with the adoption of tox-venv, which uses Python's venv, which does not install the latest setuptools by default.
      Need to avoid .eggs in recursing dirs. Ref pypa/setuptools_scm#212.
      Use tox-venv for future compatibility.
      Disable pytest-sugar until Frozenball/pytest-sugar#133 is addressed.
      Bring back pytest-sugar with a minimum version to support Pytest 3.4.
      Save the pip cache across builds. Ref pypa/setuptools#1279.
      Add workaround for build failures on Python 3.7 (yaml/pyyaml#126).
      Run flake8 with tests. Add flake8 config to ignore common exclusions. Add comments to testing and docs extras to aid with merges.
      Add appveyor badge (commented). Disable RTD by default.
      Limit workaround to affected Python
      Bump minimum pytest version
      Add pyproject.toml declaring build dependencies.
      When ignoring linter warnings, document the reason.
      Disable the (broken) IPv6 in Travis. Ref travis-ci/travis-ci#8361.
      Don't match issues if preceeded by some other indicator.
      skip_upload_docs is default
      Drop the dot; http://blog.pytest.org/2016/whats-new-in-pytest-30/
      Rely on declarative config to create long_description.
      Remove workaround for pyyaml 126.
      Revert "Remove workaround for pyyaml 126."
      We're getting close, but Python 3.7 still requires a workaround
      Use xenial to include support for Python 3.7.
      Remove release, no longer needed. Use twine instead.
      Also ignore W504 in flake8, following the indication in OCA/maintainer-quality-tools that neither W503 nor W504 are worthwhile in general.
      Release of pyyaml 3.13 seems to have fixed install issues on Python 3.7.
      Block pytest 3.7.3 due to pytest-dev/pytest#3888.
      Twiddle the docstrings to make pre-commit happy. Ref #52.
      Use Python-2-compatible super calls
      Merge pull request #108 from cherrypy/pr/52-require-client-certificates
      Update changelog. Ref #108, #52. Fixes cherrypy/cherrypy#1001.
      Merge https://github.com/jaraco/skeleton
      Run pre-commit

Sviatoslav Sydorenko (8):
      Install pyenv for OSX from master of brew
      Apply chmod on UNIX socket after creation
      Split HTTPServer.bind into 3 stages
      Turn TODO comment into FIXME
      Separate bind method for UNIX file socket
      Implement smart file premission setters
      Add changelog about #93/#110
      Partially revert "Merge https://github.com/jaraco/skeleton"

v6.5.1
======
- :issue:`93` via :pr:`110`: Improve UNIX socket fs access mode
  in :py:meth:`cheroot.server.HTTPServer.prepare` on a file socket
  when starting to listen to it.

v6.5.0
======

- :cp-issue:`1001` via :pr:`52` and :pr:`108`: Add support for
  validating client certificates.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment