From 16c99af614c39dd1bb289074fb92b3439cbc9545 Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik Date: Sep 02 2019 22:57:59 +0000 Subject: [PATCH 1/9] pyhbac: Fix warning Wdiscarded-qualifiers The macro PyDoc_STRVAR changed in python 3.8 and it defined variable with const modifier src/python/pyhbac.c: In function ‘PyInit_pyhbac’: src/python/pyhbac.c:1948:25: warning: passing argument 2 of ‘sss_exception_with_doc’ discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers] 1948 | HbacError__doc__, | ^~~~~~~~~~~~~~~~ In file included from src/python/pyhbac.c:27: ./src/util/sss_python.h:33:1: note: expected ‘char *’ but argument is of type ‘const char *’ 33 | sss_exception_with_doc(char *name, char *doc, PyObject *base, PyObject *dict); | ^~~~~~~~~~~~~~~~~~~~~~ --- diff --git a/src/python/pyhbac.c b/src/python/pyhbac.c index d78452c..99d9bb0 100644 --- a/src/python/pyhbac.c +++ b/src/python/pyhbac.c @@ -1944,8 +1944,7 @@ initpyhbac(void) /* The HBAC module exception */ PyExc_HbacError = sss_exception_with_doc( - discard_const_p(char, "hbac.HbacError"), - HbacError__doc__, + "hbac.HbacError", HbacError__doc__, PyExc_EnvironmentError, NULL); Py_INCREF(PyExc_HbacError); ret = PyModule_AddObject(m, sss_py_const_p(char, "HbacError"), PyExc_HbacError); diff --git a/src/util/sss_python.c b/src/util/sss_python.c index 0e2f971..2b01c6e 100644 --- a/src/util/sss_python.c +++ b/src/util/sss_python.c @@ -21,10 +21,14 @@ #include "src/util/sss_python.h" PyObject * -sss_exception_with_doc(char *name, char *doc, PyObject *base, PyObject *dict) +sss_exception_with_doc(const char *name, const char *doc, PyObject *base, + PyObject *dict) { -#if PY_VERSION_HEX >= 0x02070000 +#if PY_VERSION_HEX >= 0x03080000 return PyErr_NewExceptionWithDoc(name, doc, base, dict); +#elif PY_VERSION_HEX >= 0x02070000 + return PyErr_NewExceptionWithDoc(discard_const_p(char, name), + discard_const_p(char, doc), base, dict); #else int result; PyObject *ret = NULL; @@ -48,7 +52,7 @@ sss_exception_with_doc(char *name, char *doc, PyObject *base, PyObject *dict) goto failure; } - ret = PyErr_NewException(name, base, dict); + ret = PyErr_NewException(discard_const_p(char, name), base, dict); failure: Py_XDECREF(mydict); return ret; diff --git a/src/util/sss_python.h b/src/util/sss_python.h index 26ecd71..327a4c3 100644 --- a/src/util/sss_python.h +++ b/src/util/sss_python.h @@ -30,7 +30,8 @@ /* Exceptions compatibility */ PyObject * -sss_exception_with_doc(char *name, char *doc, PyObject *base, PyObject *dict); +sss_exception_with_doc(const char *name, const char *doc, PyObject *base, + PyObject *dict); /* Convenience macros */ #define TYPE_READY(module, type, name) do { \ From bd28b145b8bd671caf93be067e0c37362dbc2611 Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik Date: Sep 02 2019 22:57:59 +0000 Subject: [PATCH 2/9] test_pam_responder: Fix unicore error Use raw strings instead; other alternative would be to escepe backslash E File "/home/build/sssd/src/tests/intg/test_pam_responder.py", line 647 E assert err.find("pam_authenticate for user [auth_only\user1]: " + E ^ E SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 36-37: truncated \uXXXX escape --- diff --git a/src/tests/intg/test_pam_responder.py b/src/tests/intg/test_pam_responder.py index 74d12d8..a613505 100644 --- a/src/tests/intg/test_pam_responder.py +++ b/src/tests/intg/test_pam_responder.py @@ -644,5 +644,5 @@ def test_sc_auth_name_format(simple_pam_cert_auth_name_format, env_for_sssctl): if sssctl.wait() != 0: raise Exception("sssctl failed") - assert err.find("pam_authenticate for user [auth_only\user1]: " + + assert err.find(r"pam_authenticate for user [auth_only\user1]: " + "Success") != -1 From 6bdba90e0060bd4a1a4fc98ee6306660a5a1ffa6 Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik Date: Sep 02 2019 22:58:08 +0000 Subject: [PATCH 3/9] SSSDConfig: Add minimal test for parse method --- diff --git a/Makefile.am b/Makefile.am index 5ad959c..0149b28 100644 --- a/Makefile.am +++ b/Makefile.am @@ -473,6 +473,7 @@ dist_noinst_DATA = \ src/config/testconfigs/sssd-invalid.conf \ src/config/testconfigs/sssd-invalid-badbool.conf \ src/config/testconfigs/sssd-nonexisting-services-domains.conf \ + src/config/testconfigs/sssd-test-parse.conf \ src/config/etc/sssd.api.d/crash_test_dummy \ contrib/ci/README.md \ contrib/ci/configure.sh \ diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py index 95dfd67..ee84d80 100755 --- a/src/config/SSSDConfigTest.py +++ b/src/config/SSSDConfigTest.py @@ -2089,6 +2089,33 @@ class SSSDConfigTestSSSDConfig(unittest.TestCase): self.assertRaises(SSSDConfig.NoDomainError, sssdconfig.activate_domain, self) + def testParse(self): + sssdconfig = SSSDConfig.SSSDConfig(srcdir + "/etc/sssd.api.conf", + srcdir + "/etc/sssd.api.d") + + with open(srcdir + "/testconfigs/sssd-test-parse.conf", "r") as f: + data = sssdconfig.parse(f) + + self.assertEqual(len(data), 4) + self.assertEqual(data[-1], {'type': "section", + 'name': "nss", + 'value': [{'type': 'option', + 'name': 'debug_level', + 'value': '1'}, + {'type': 'empty', + 'name': 'empty'}]}) + + with open(srcdir + "/testconfigs/sssd-valid.conf", "r") as f: + data = sssdconfig.parse(f) + + self.assertEqual(len(data), 10) + self.assertEqual(data[-1], {'name': "sudo", + 'type': "section", + 'value': [{'type': 'option', + 'name': 'debug_level', + 'value': '0xfC10'}]}) + + if __name__ == "__main__": error = 0 diff --git a/src/config/testconfigs/sssd-test-parse.conf b/src/config/testconfigs/sssd-test-parse.conf new file mode 100644 index 0000000..b48221b --- /dev/null +++ b/src/config/testconfigs/sssd-test-parse.conf @@ -0,0 +1,12 @@ +[domain/active] + +[domain/inactive] + +[sssd] +domains = active +services = nss + +[nss] +debug_level = 1 + +[pam] From 29d901fb6c22feb999f671f3c329c6d1a01828e3 Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik Date: Sep 02 2019 22:58:21 +0000 Subject: [PATCH 4/9] SSSDConfig: Fix SyntaxWarning "is not" with a literal There is a warning with python 3.8 /usr/lib/python3.8/site-packages/SSSDConfig/ipachangeconf.py:399: SyntaxWarning: "is not" with a literal. Did you mean "!="? if len(sectopts) is not 0: --- diff --git a/src/config/SSSDConfig/ipachangeconf.py b/src/config/SSSDConfig/ipachangeconf.py index 3348112..d26676f 100644 --- a/src/config/SSSDConfig/ipachangeconf.py +++ b/src/config/SSSDConfig/ipachangeconf.py @@ -396,7 +396,7 @@ class IPAChangeConf(object): curopts.append(self.parseLine(line)) #Add last section if any - if len(sectopts) is not 0: + if sectopts: opts.append({'name':section, 'type':'section', 'value':sectopts}) return opts From 360aced5f780711b9cfdad9b128bb82d7c0e29f6 Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik Date: Sep 02 2019 23:15:24 +0000 Subject: [PATCH 5/9] TESTS: Add minimal test for pysss encrypt --- diff --git a/Makefile.am b/Makefile.am index 0149b28..c78f45b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -346,12 +346,14 @@ PYTHON_TESTS = if BUILD_PYTHON2_BINDINGS PYTHON_TESTS += src/config/SSSDConfigTest.py2.sh \ src/tests/pyhbac-test.py2.sh \ + src/tests/pysss-test.py2.sh \ src/tests/pysss_murmur-test.py2.sh \ $(NULL) endif if BUILD_PYTHON3_BINDINGS PYTHON_TESTS += src/config/SSSDConfigTest.py3.sh \ src/tests/pyhbac-test.py3.sh \ + src/tests/pysss-test.py3.sh \ src/tests/pysss_murmur-test.py3.sh \ $(NULL) endif @@ -456,6 +458,9 @@ dist_noinst_SCRIPTS = \ src/tests/pyhbac-test.py \ src/tests/pyhbac-test.py2.sh \ src/tests/pyhbac-test.py3.sh \ + src/tests/pysss-test.py \ + src/tests/pysss-test.py2.sh \ + src/tests/pysss-test.py3.sh \ src/tests/pysss_murmur-test.py \ src/tests/pysss_murmur-test.py2.sh \ src/tests/pysss_murmur-test.py3.sh \ diff --git a/src/tests/pysss-test.py b/src/tests/pysss-test.py new file mode 100755 index 0000000..30bc074 --- /dev/null +++ b/src/tests/pysss-test.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python +# SSSD +# +# SSSD python SSS API tests +# +# Copyright (C) Red Hat +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from __future__ import print_function + +import unittest +import sys +import os +import tempfile + +BUILD_DIR = os.getenv('builddir') or "." +TEST_DIR = os.getenv('SSS_TEST_DIR') or "." +MODPATH = tempfile.mkdtemp(prefix="tp_pysss_", dir=TEST_DIR) + + +class PysssImport(unittest.TestCase): + def setUp(self): + " Make sure we load the in-tree module " + self.system_path = sys.path[:] + sys.path = [MODPATH] + + def tearDown(self): + " Restore the system path " + sys.path = self.system_path + + def test_import(self): + " Import the module and assert it comes from tree " + try: + dest_module_path = MODPATH + "/pysss.so" + + if sys.version_info[0] > 2: + src_module_path = BUILD_DIR + "/.libs/_py3sss.so" + else: + src_module_path = BUILD_DIR + "/.libs/_py2sss.so" + + src_module_path = os.path.abspath(src_module_path) + os.symlink(src_module_path, dest_module_path) + + import pysss + except ImportError as ex: + print("Could not load the pysss module. Please check if it is " + "compiled", file=sys.stderr) + raise ex + self.assertEqual(pysss.__file__, MODPATH + "/pysss.so") + + +class PysssEncryptTest(unittest.TestCase): + def test_encrypt(self): + obfuscator = pysss.password() + + val1 = obfuscator.encrypt("123", obfuscator.AES_256) + self.assertEqual(len(val1), 96) + + val2 = obfuscator.encrypt("123", obfuscator.AES_256) + self.assertEqual(len(val2), 96) + + self.assertNotEqual(val1, val2) + + +if __name__ == "__main__": + error = 0 + + suite = unittest.TestLoader().loadTestsFromTestCase(PysssImport) + res = unittest.TextTestRunner().run(suite) + if not res.wasSuccessful(): + error |= 0x1 + # need to bail out here because pysss could not be imported + sys.exit(error) + + # import the pysss module into the global namespace, but make sure it's + # the one in tree + sys.path.insert(0, MODPATH) + import pysss + + loadTestsFromTestCase = unittest.TestLoader().loadTestsFromTestCase + + suite = loadTestsFromTestCase(PysssEncryptTest) + res = unittest.TextTestRunner().run(suite) + if not res.wasSuccessful(): + error |= 0x2 + + sys.exit(error) diff --git a/src/tests/pysss-test.py2.sh b/src/tests/pysss-test.py2.sh new file mode 100755 index 0000000..5907361 --- /dev/null +++ b/src/tests/pysss-test.py2.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +SCRIPT=$(readlink -f "$0") +SCRIPT_PATH=$(dirname "$SCRIPT") +exec python2 $SCRIPT_PATH/pysss-test.py diff --git a/src/tests/pysss-test.py3.sh b/src/tests/pysss-test.py3.sh new file mode 100755 index 0000000..db9160f --- /dev/null +++ b/src/tests/pysss-test.py3.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +SCRIPT=$(readlink -f "$0") +SCRIPT_PATH=$(dirname "$SCRIPT") +exec python3 $SCRIPT_PATH/pysss-test.py From f0a7da86466e770efbcb63469a61fb52e9b44cc1 Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik Date: Sep 02 2019 23:15:24 +0000 Subject: [PATCH 6/9] pysss: Fix DeprecationWarning PY_SSIZE_T_CLEAN src/tests/pysss-test.py:73: DeprecationWarning: PY_SSIZE_T_CLEAN will be required for '#' formats val1 = obfuscator.encrypt("123", obfuscator.AES_256) These were introduced by https://bugs.python.org/issue36381 to warn about an upcoming Python C API change. The meaning of PY_SSIZE_T_CLEAN is described in https://python.readthedocs.io/en/stable/c-api/arg.html#strings-and-buffers. --- diff --git a/src/python/pysss.c b/src/python/pysss.c index 78b8de0..4a0aca0 100644 --- a/src/python/pysss.c +++ b/src/python/pysss.c @@ -20,6 +20,7 @@ #include "config.h" +#define PY_SSIZE_T_CLEAN 1 #include #include #include @@ -68,7 +69,7 @@ static PyObject *py_sss_encrypt(PySssPasswordObject *self, PyObject *args) { char *password = NULL; - int plen; /* may contain NULL bytes */ + Py_ssize_t plen; /* may contain NULL bytes */ char *obfpwd = NULL; TALLOC_CTX *tctx = NULL; int ret; @@ -87,7 +88,7 @@ static PyObject *py_sss_encrypt(PySssPasswordObject *self, return NULL; } - ret = sss_password_encrypt(tctx, password, plen+1, + ret = sss_password_encrypt(tctx, password, (int)(plen + 1), mode, &obfpwd); if (ret != EOK) { PyErr_SetSssError(ret); From 63b520df8ef2f2f6248a517e2b0c440956b979ae Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik Date: Sep 02 2019 23:15:24 +0000 Subject: [PATCH 7/9] pysss_murmur: Fix DeprecationWarning PY_SSIZE_T_CLEAN src/tests/pysss_murmur-test.py:93: DeprecationWarning: PY_SSIZE_T_CLEAN will be required for '#' formats hash_val = pysss_murmur.murmurhash3(sid_str, 0, seed) src/tests/pysss_murmur-test.py:96: DeprecationWarning: PY_SSIZE_T_CLEAN will be required for '#' formats hash_val = pysss_murmur.murmurhash3(sid_str, len(sid_str), seed) These were introduced by https://bugs.python.org/issue36381 to warn about an upcoming Python C API change. The meaning of PY_SSIZE_T_CLEAN is described in https://python.readthedocs.io/en/stable/c-api/arg.html#strings-and-buffers. --- diff --git a/src/python/pysss_murmur.c b/src/python/pysss_murmur.c index bcb2b81..4db773c 100644 --- a/src/python/pysss_murmur.c +++ b/src/python/pysss_murmur.c @@ -20,6 +20,7 @@ #include "config.h" +#define PY_SSIZE_T_CLEAN 1 #include #include "util/sss_python.h" @@ -38,7 +39,7 @@ static PyObject * py_murmurhash3(PyObject *module, PyObject *args) long key_len; long long seed; uint32_t hash; - int input_len; + Py_ssize_t input_len; if (!PyArg_ParseTuple(args, sss_py_const_p(char, "z#lL"), &key, &input_len, &key_len, &seed)) { From 6e2310d4e7f16ee3ecc23cc6ec6028e92eaed68f Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik Date: Sep 02 2019 23:15:24 +0000 Subject: [PATCH 8/9] test_pam_responder: Fix DeprecationWarning invalid escape sequence test_pam_responder.py:151 src/tests/intg/test_pam_responder.py:151: DeprecationWarning: invalid escape sequence \% return unindent("""\ Merges: https://pagure.io/SSSD/sssd/pull-request/4076 --- diff --git a/src/tests/intg/test_pam_responder.py b/src/tests/intg/test_pam_responder.py index a613505..5809b83 100644 --- a/src/tests/intg/test_pam_responder.py +++ b/src/tests/intg/test_pam_responder.py @@ -168,7 +168,7 @@ def format_pam_cert_auth_conf_name_format(config): [domain/auth_only] use_fully_qualified_names = True - full_name_format = %2$s\%1$s + full_name_format = %2$s\\%1$s debug_level = 10 id_provider = files From 429e083f5c0de7ea561eba41a1b9b7efcb7c3e12 Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik Date: Sep 03 2019 21:21:35 +0000 Subject: [PATCH 9/9] testlib: Fix SyntaxWarning "is" with a literal --- diff --git a/src/tests/python/sssd/testlib/common/libkrb5.py b/src/tests/python/sssd/testlib/common/libkrb5.py index e3d9ad0..8f5788d 100644 --- a/src/tests/python/sssd/testlib/common/libkrb5.py +++ b/src/tests/python/sssd/testlib/common/libkrb5.py @@ -169,13 +169,13 @@ class krb5srv(object): if service is None: service = 'host' - if p_type is 'user': + if p_type == 'user': add_principal = "add_principal -clearpolicy"\ " -pw %s %s@%s" % (password, principal, self.krb_realm) kadmin_local_cmd = ['kadmin.local', '-r', self.krb_realm, '-q', add_principal] - elif p_type is 'admin': + elif p_type == 'admin': add_principal = "add_principal -clearpolicy"\ " -pw %s %s/%s" % (password, service, 'admin') kadmin_local_cmd = ['kadmin.local', '-r', self.krb_realm,