1
# Copyright 2014-2015 MongoDB, Inc.
3
# Licensed under the Apache License, Version 2.0 (the "License"); you
4
# may not use this file except in compliance with the License. You
5
# may obtain a copy of the License at
7
# http://www.apache.org/licenses/LICENSE-2.0
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12
# implied. See the License for the specific language governing
13
# permissions and limitations under the License.
15
"""Support for SSL in PyMongo."""
34
HAVE_WINCERTSTORE = False
36
from wincertstore import CertFile
37
HAVE_WINCERTSTORE = True
41
from bson.py3compat import string_type
42
from pymongo.errors import ConfigurationError
44
_WINCERTSLOCK = threading.Lock()
49
# Python 3.2 and above.
50
from ssl import SSLContext
52
from pymongo.ssl_context import SSLContext
54
def validate_cert_reqs(option, value):
55
"""Validate the cert reqs are valid. It must be None or one of the
56
three values ``ssl.CERT_NONE``, ``ssl.CERT_OPTIONAL`` or
57
``ssl.CERT_REQUIRED``.
61
elif isinstance(value, string_type) and hasattr(ssl, value):
62
value = getattr(ssl, value)
64
if value in (ssl.CERT_NONE, ssl.CERT_OPTIONAL, ssl.CERT_REQUIRED):
66
raise ValueError("The value of %s must be one of: "
67
"`ssl.CERT_NONE`, `ssl.CERT_OPTIONAL` or "
68
"`ssl.CERT_REQUIRED" % (option,))
71
"""Set _WINCERTS to an instance of wincertstore.Certfile."""
75
certfile.addstore("CA")
76
certfile.addstore("ROOT")
77
atexit.register(certfile.close)
81
# XXX: Possible future work.
82
# - Support CRL files? Only supported by CPython >= 2.7.9 and >= 3.4
83
# http://bugs.python.org/issue8813
84
# - OCSP? Not supported by python at all.
85
# http://bugs.python.org/issue17123
86
# - Setting OP_NO_COMPRESSION? The server doesn't yet.
87
# - Adding an ssl_context keyword argument to MongoClient? This might
88
# be useful for sites that have unusual requirements rather than
89
# trying to expose every SSLContext option through a keyword/uri
91
def get_ssl_context(*args):
92
"""Create and return an SSLContext object."""
93
certfile, keyfile, ca_certs, cert_reqs = args
94
# Note PROTOCOL_SSLv23 is about the most misleading name imaginable.
95
# This configures the server and client to negotiate the
96
# highest protocol version they both support. A very good thing.
97
ctx = SSLContext(ssl.PROTOCOL_SSLv23)
98
if hasattr(ctx, "options"):
99
# Explicitly disable SSLv2 and SSLv3. Note that up to
100
# date versions of MongoDB 2.4 and above already do this,
101
# python disables SSLv2 by default in >= 2.7.7 and >= 3.3.4
102
# and SSLv3 in >= 3.4.3. There is no way for us to do this
103
# explicitly for python 2.6 or 2.7 before 2.7.9.
104
ctx.options |= getattr(ssl, "OP_NO_SSLv2", 0)
105
ctx.options |= getattr(ssl, "OP_NO_SSLv3", 0)
106
if certfile is not None:
107
ctx.load_cert_chain(certfile, keyfile)
108
if ca_certs is not None:
109
ctx.load_verify_locations(ca_certs)
110
elif cert_reqs != ssl.CERT_NONE:
111
# CPython >= 2.7.9 or >= 3.4.0, pypy >= 2.5.1
112
if hasattr(ctx, "load_default_certs"):
113
ctx.load_default_certs()
114
# Python >= 3.2.0, useless on Windows.
115
elif (sys.platform != "win32" and
116
hasattr(ctx, "set_default_verify_paths")):
117
ctx.set_default_verify_paths()
118
elif sys.platform == "win32" and HAVE_WINCERTSTORE:
120
if _WINCERTS is None:
122
ctx.load_verify_locations(_WINCERTS.name)
124
ctx.load_verify_locations(certifi.where())
126
raise ConfigurationError(
127
"`ssl_cert_reqs` is not ssl.CERT_NONE and no system "
128
"CA certificates could be loaded. `ssl_ca_certs` is "
130
ctx.verify_mode = ssl.CERT_REQUIRED if cert_reqs is None else cert_reqs
133
def validate_cert_reqs(option, dummy):
134
"""No ssl module, raise ConfigurationError."""
135
raise ConfigurationError("The value of %s is set but can't be "
136
"validated. The ssl module is not available"
139
def get_ssl_context(*dummy):
140
"""No ssl module, raise ConfigurationError."""
141
raise ConfigurationError("The ssl module is not available.")