Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6d7ad13

Browse files
committed
Issue #18143: Implement ssl.get_default_verify_paths() in order to debug
the default locations for cafile and capath.
1 parent 302b8c3 commit 6d7ad13

5 files changed

Lines changed: 97 additions & 1 deletion

File tree

Doc/library/ssl.rst

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,23 @@ Certificate handling
343343
Given a certificate as an ASCII PEM string, returns a DER-encoded sequence of
344344
bytes for that same certificate.
345345

346+
.. function:: get_default_verify_paths()
347+
348+
Returns a named tuple with paths to OpenSSL's default cafile and capath.
349+
The paths are the same as used by
350+
:meth:`SSLContext.set_default_verify_paths`. The return value is a
351+
:term:`named tuple` ``DefaultVerifyPaths``:
352+
353+
* :attr:`cafile` - resolved path to cafile or None if the file doesn't exist,
354+
* :attr:`capath` - resolved path to capath or None if the directory doesn't exist,
355+
* :attr:`openssl_cafile_env` - OpenSSL's environment key that points to a cafile,
356+
* :attr:`openssl_cafile` - hard coded path to a cafile,
357+
* :attr:`openssl_capath_env` - OpenSSL's environment key that points to a capath,
358+
* :attr:`openssl_capath` - hard coded path to a capath directory
359+
360+
.. versionadded:: 3.4
361+
362+
346363
Constants
347364
^^^^^^^^^
348365

@@ -787,7 +804,8 @@ to speed up repeated connections from the same clients.
787804
other peers' certificates when :data:`verify_mode` is other than
788805
:data:`CERT_NONE`. At least one of *cafile* or *capath* must be specified.
789806

790-
The *cafile* string, if present, is the path to a file of concatenated
807+
The *cafile* string, if present, is the p
808+
ath to a file of concatenated
791809
CA certificates in PEM format. See the discussion of
792810
:ref:`ssl-certificates` for more information about how to arrange the
793811
certificates in this file.

Lib/ssl.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@
8989

9090
import textwrap
9191
import re
92+
import os
93+
import collections
9294

9395
import _ssl # if we can't import it, let the error propagate
9496

@@ -222,6 +224,24 @@ def match_hostname(cert, hostname):
222224
"subjectAltName fields were found")
223225

224226

227+
DefaultVerifyPaths = collections.namedtuple("DefaultVerifyPaths",
228+
"cafile capath openssl_cafile_env openssl_cafile openssl_capath_env "
229+
"openssl_capath")
230+
231+
def get_default_verify_paths():
232+
"""Return paths to default cafile and capath.
233+
"""
234+
parts = _ssl.get_default_verify_paths()
235+
236+
# environment vars shadow paths
237+
cafile = os.environ.get(parts[0], parts[1])
238+
capath = os.environ.get(parts[2], parts[3])
239+
240+
return DefaultVerifyPaths(cafile if os.path.isfile(cafile) else None,
241+
capath if os.path.isdir(capath) else None,
242+
*parts)
243+
244+
225245
class SSLContext(_SSLContext):
226246
"""An SSLContext holds various SSL-related configuration options and
227247
data, such as certificates and possibly a private key."""

Lib/test/test_ssl.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,19 @@ def test_dealloc_warn(self):
394394
support.gc_collect()
395395
self.assertIn(r, str(cm.warning.args[0]))
396396

397+
def test_get_default_verify_paths(self):
398+
paths = ssl.get_default_verify_paths()
399+
self.assertEqual(len(paths), 6)
400+
self.assertIsInstance(paths, ssl.DefaultVerifyPaths)
401+
402+
with support.EnvironmentVarGuard() as env:
403+
env["SSL_CERT_DIR"] = CAPATH
404+
env["SSL_CERT_FILE"] = CERTFILE
405+
paths = ssl.get_default_verify_paths()
406+
self.assertEqual(paths.cafile, CERTFILE)
407+
self.assertEqual(paths.capath, CAPATH)
408+
409+
397410
class ContextTests(unittest.TestCase):
398411

399412
@skip_if_broken_ubuntu_ssl

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ Core and Builtins
115115
Library
116116
-------
117117

118+
- Issue #18143: Implement ssl.get_default_verify_paths() in order to debug
119+
the default locations for cafile and capath.
120+
118121
- Issue #17314: Move multiprocessing.forking over to importlib.
119122

120123
- Issue #11959: SMTPServer and SMTPChannel now take an optional map, use of

Modules/_ssl.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2761,6 +2761,46 @@ fails or if it does provide enough data to seed PRNG.");
27612761

27622762
#endif
27632763

2764+
PyDoc_STRVAR(PySSL_get_default_verify_paths_doc,
2765+
"get_default_verify_paths() -> tuple\n\
2766+
\n\
2767+
Return search paths and environment vars that are used by SSLContext's\n\
2768+
set_default_verify_paths() to load default CAs. The values are\n\
2769+
'cert_file_env', 'cert_file', 'cert_dir_env', 'cert_dir'.");
2770+
2771+
static PyObject *
2772+
get_default_verify_paths(PyObject *self)
2773+
{
2774+
PyObject *ofile_env = NULL;
2775+
PyObject *ofile = NULL;
2776+
PyObject *odir_env = NULL;
2777+
PyObject *odir = NULL;
2778+
2779+
#define convert(info, target) { \
2780+
const char *tmp = (info); \
2781+
target = NULL; \
2782+
if (!tmp) { Py_INCREF(Py_None); target = Py_None; } \
2783+
else if ((target = PyUnicode_DecodeFSDefault(tmp)) == NULL) { \
2784+
target = PyBytes_FromString(tmp); } \
2785+
if (!target) goto error; \
2786+
} while(0)
2787+
2788+
convert(X509_get_default_cert_file_env(), ofile_env);
2789+
convert(X509_get_default_cert_file(), ofile);
2790+
convert(X509_get_default_cert_dir_env(), odir_env);
2791+
convert(X509_get_default_cert_dir(), odir);
2792+
#undef convert
2793+
2794+
return Py_BuildValue("(OOOO)", ofile_env, ofile, odir_env, odir);
2795+
2796+
error:
2797+
Py_XDECREF(ofile_env);
2798+
Py_XDECREF(ofile);
2799+
Py_XDECREF(odir_env);
2800+
Py_XDECREF(odir);
2801+
return NULL;
2802+
}
2803+
27642804

27652805

27662806
/* List of functions exported by this module. */
@@ -2779,6 +2819,8 @@ static PyMethodDef PySSL_methods[] = {
27792819
PySSL_RAND_egd_doc},
27802820
{"RAND_status", (PyCFunction)PySSL_RAND_status, METH_NOARGS,
27812821
PySSL_RAND_status_doc},
2822+
{"get_default_verify_paths", (PyCFunction)get_default_verify_paths,
2823+
METH_NOARGS, PySSL_get_default_verify_paths_doc},
27822824
#endif
27832825
{NULL, NULL} /* Sentinel */
27842826
};

0 commit comments

Comments
 (0)