diff --git a/pygit2/settings.py b/pygit2/settings.py index 9d5fd2f6a..43904c5b0 100644 --- a/pygit2/settings.py +++ b/pygit2/settings.py @@ -24,6 +24,9 @@ # along with this program; see the file COPYING. If not, write to # the Free Software Foundation, 51 Franklin Street, Fifth Floor, # Boston, MA 02110-1301, USA. +"""Settings mapping.""" + +from ssl import get_default_verify_paths from _pygit2 import option from _pygit2 import GIT_OPT_GET_SEARCH_PATH, GIT_OPT_SET_SEARCH_PATH @@ -33,9 +36,13 @@ from _pygit2 import GIT_OPT_GET_CACHED_MEMORY from _pygit2 import GIT_OPT_ENABLE_CACHING from _pygit2 import GIT_OPT_SET_CACHE_MAX_SIZE +from _pygit2 import GIT_OPT_SET_SSL_CERT_LOCATIONS + + +__metaclass__ = type # make all classes new-style by default -class SearchPathList(object): +class SearchPathList: def __getitem__(self, key): return option(GIT_OPT_GET_SEARCH_PATH, key) @@ -44,13 +51,20 @@ def __setitem__(self, key, value): option(GIT_OPT_SET_SEARCH_PATH, key, value) -class Settings(object): - """Library-wide settings""" +class Settings: + """Library-wide settings interface.""" - __slots__ = [] + __slots__ = '_default_tls_verify_paths', '_ssl_cert_dir', '_ssl_cert_file' _search_path = SearchPathList() + def __init__(self): + self._default_tls_verify_paths = get_default_verify_paths() + self.set_ssl_cert_locations( + self._default_tls_verify_paths.cafile, + self._default_tls_verify_paths.capath, + ) + @property def search_path(self): """Configuration file search path. @@ -101,4 +115,39 @@ def cache_object_limit(self, object_type, value): """ return option(GIT_OPT_SET_CACHE_OBJECT_LIMIT, object_type, value) + @property + def ssl_cert_file(self): + """TLS certificate file path.""" + return self._ssl_cert_file + @ssl_cert_file.setter + def ssl_cert_file(self, value): + """Set the TLS cert file path.""" + self.set_ssl_cert_locations(value, self._ssl_cert_dir) + + @ssl_cert_file.deleter + def ssl_cert_file(self): + """Reset the TLS cert file path.""" + self.ssl_cert_file = self._default_tls_verify_paths.cafile + + @property + def ssl_cert_dir(self): + """TLS certificates lookup directory path.""" + return self._ssl_cert_dir + + @ssl_cert_dir.setter + def ssl_cert_dir(self, value): + """Set the TLS certificate lookup folder.""" + self.set_ssl_cert_locations(self._ssl_cert_file, value) + + @ssl_cert_dir.deleter + def ssl_cert_dir(self): + """Reset the TLS certificate lookup folder.""" + self.ssl_cert_dir = self._default_tls_verify_paths.capath + + def set_ssl_cert_locations(self, ssl_cert_file, ssl_cert_dir): + """Set both file path and lookup dir for TLS certs in libgit2. + """ + option(GIT_OPT_SET_SSL_CERT_LOCATIONS, ssl_cert_file, ssl_cert_dir) + self._ssl_cert_file = ssl_cert_file + self._ssl_cert_dir = ssl_cert_dir diff --git a/src/options.c b/src/options.c index 7e3e1f089..0968277d3 100644 --- a/src/options.c +++ b/src/options.c @@ -272,6 +272,36 @@ option(PyObject *self, PyObject *args) return tup; } + case GIT_OPT_SET_SSL_CERT_LOCATIONS: + { + PyObject *py_file, *py_dir; + const char *file_path, *dir_path; + int err; + + py_file = PyTuple_GetItem(args, 1); + py_dir = PyTuple_GetItem(args, 2); + + /* py_file and py_dir are only valid if they are strings */ + if (PyUnicode_Check(py_file) || PyBytes_Check(py_file)) { + file_path = py_str_to_c_str(py_file, Py_FileSystemDefaultEncoding); + } else { + file_path = NULL; + } + + if (PyUnicode_Check(py_dir) || PyBytes_Check(py_dir)) { + dir_path = py_str_to_c_str(py_dir, Py_FileSystemDefaultEncoding); + } else { + dir_path = NULL; + } + + err = git_libgit2_opts(GIT_OPT_SET_SSL_CERT_LOCATIONS, file_path, dir_path); + + if (err < 0) + return Error_set(err); + + Py_RETURN_NONE; + } + } PyErr_SetString(PyExc_ValueError, "unknown/unsupported option value"); diff --git a/src/pygit2.c b/src/pygit2.c index 06141cef9..defd32f06 100644 --- a/src/pygit2.c +++ b/src/pygit2.c @@ -242,6 +242,7 @@ moduleinit(PyObject* m) ADD_CONSTANT_INT(m, GIT_OPT_GET_CACHED_MEMORY); ADD_CONSTANT_INT(m, GIT_OPT_ENABLE_CACHING); ADD_CONSTANT_INT(m, GIT_OPT_SET_CACHE_MAX_SIZE); + ADD_CONSTANT_INT(m, GIT_OPT_SET_SSL_CERT_LOCATIONS); /* Errors */ GitError = PyErr_NewException("_pygit2.GitError", NULL, NULL);