ssl: support client certificates

Password-protected keys are not supported.
This commit is contained in:
Ben Boeckel 2015-02-25 00:07:26 -05:00
parent 665b0cefaf
commit 9223899996
3 changed files with 42 additions and 7 deletions

View file

@ -53,4 +53,24 @@ the system certificate CAs. Normally these two stores are similar enough for
you not to care. If the behavior on your system is somehow confusing, your best
bet is explicitly setting the SSL options above.
.. _ssl-client-certs:
Client Certificates
-------------------
Client certificates may be specified with the ``auth_cert`` parameter. If the
key and certificate are stored in the same file, it may be a string::
[storage foo]
type = caldav
...
auth_cert = "/path/to/certificate"
If the key and certificate are separate, a list may be used::
[storage foo]
type = caldav
...
auth_cert = ["/path/to/certificate", "/path/to/key"]
.. _requests: http://www.python-requests.org/

View file

@ -9,7 +9,7 @@ from requests.exceptions import HTTPError
from .base import Item, Storage
from .http import HTTP_STORAGE_PARAMETERS, USERAGENT, prepare_auth, \
prepare_verify
prepare_verify, prepare_client_cert
from .. import exceptions, log, utils
from ..utils.compat import text_type
@ -208,7 +208,8 @@ class DavSession(object):
'''
def __init__(self, url, username='', password='', verify=True, auth=None,
useragent=USERAGENT, verify_fingerprint=None):
useragent=USERAGENT, verify_fingerprint=None,
auth_cert=None):
if username and not password:
password = utils.get_password(username, url)
@ -216,6 +217,7 @@ class DavSession(object):
'verify': prepare_verify(verify),
'auth': prepare_auth(auth, username, password),
'verify_fingerprint': verify_fingerprint,
'cert': prepare_client_cert(auth_cert),
}
self.useragent = useragent
self.url = url.rstrip('/') + '/'
@ -270,12 +272,13 @@ class DavStorage(Storage):
def __init__(self, url, username='', password='', verify=True, auth=None,
useragent=USERAGENT, unsafe_href_chars='@',
verify_fingerprint=None, **kwargs):
verify_fingerprint=None, auth_cert=None, **kwargs):
super(DavStorage, self).__init__(**kwargs)
url = url.rstrip('/') + '/'
self.session = DavSession(url, username, password, verify, auth,
useragent, verify_fingerprint)
useragent, verify_fingerprint,
auth_cert)
self.unsafe_href_chars = unsafe_href_chars
# defined for _repr_attributes
@ -286,7 +289,7 @@ class DavStorage(Storage):
def _get_session(cls, **kwargs):
discover_args, _ = utils.split_dict(kwargs, lambda key: key in (
'url', 'username', 'password', 'verify', 'auth', 'useragent',
'verify_fingerprint',
'verify_fingerprint', 'auth_cert',
))
return DavSession(**discover_args)

View file

@ -37,6 +37,14 @@ def prepare_verify(verify):
return verify
def prepare_client_cert(cert):
if isinstance(cert, (text_type, bytes)):
cert = expand_path(cert)
elif isinstance(cert, list):
cert = map(prepare_client_cert, cert)
return cert
HTTP_STORAGE_PARAMETERS = '''
:param username: Username for authentication.
:param password: Password for authentication.
@ -49,6 +57,8 @@ HTTP_STORAGE_PARAMETERS = '''
:param auth: Optional. Either ``basic``, ``digest`` or ``guess``. Default
``guess``. If you know yours, consider setting it explicitly for
performance.
:param auth_cert: Optional. Either a path to a certificate with a client
certificate and the key or a list of paths to the files with them.
:param useragent: Default ``vdirsyncer``.
'''
@ -82,7 +92,8 @@ class HttpStorage(Storage):
_items = None
def __init__(self, url, username='', password='', verify=True, auth=None,
useragent=USERAGENT, verify_fingerprint=None, **kwargs):
useragent=USERAGENT, verify_fingerprint=None, auth_cert=None,
**kwargs):
super(HttpStorage, self).__init__(**kwargs)
if username and not password:
@ -92,7 +103,8 @@ class HttpStorage(Storage):
'verify': prepare_verify(verify),
'verify_fingerprint': verify_fingerprint,
'auth': prepare_auth(auth, username, password),
'latin1_fallback': False
'cert': prepare_client_cert(auth_cert),
'latin1_fallback': False,
}
self.username, self.password = username, password
self.useragent = useragent