diff --git a/Doc/library/spwd.rst b/Doc/library/spwd.rst index 58be78f0175..53f8c09e09d 100644 --- a/Doc/library/spwd.rst +++ b/Doc/library/spwd.rst @@ -54,6 +54,9 @@ The following functions are defined: Return the shadow password database entry for the given user name. + .. versionchanged:: 3.6 + Raises a :exc:`PermissionError` instead of :exc:`KeyError` if the user + doesn't have privileges. .. function:: getspall() diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index 1129cb34349..904605861b7 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -471,6 +471,8 @@ Changes in the Python API the exception will stop a single-threaded server. (Contributed by Martin Panter in :issue:`23430`.) +* :func:`spwd.getspnam` now raises a :exc:`PermissionError` instead of + :exc:`KeyError` if the user doesn't have privileges. Changes in the C API -------------------- diff --git a/Lib/test/test_spwd.py b/Lib/test/test_spwd.py index bea7ab1ba5d..fca809ef376 100644 --- a/Lib/test/test_spwd.py +++ b/Lib/test/test_spwd.py @@ -56,5 +56,15 @@ class TestSpwdRoot(unittest.TestCase): self.assertRaises(TypeError, spwd.getspnam, bytes_name) +@unittest.skipUnless(hasattr(os, 'geteuid') and os.geteuid() != 0, + 'non-root user required') +class TestSpwdNonRoot(unittest.TestCase): + + def test_getspnam_exception(self): + with self.assertRaises(PermissionError) as cm: + spwd.getspnam('bin') + self.assertEqual(str(cm.exception), '[Errno 13] Permission denied') + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS index fe3071ecb54..ae0a1001686 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -226,6 +226,9 @@ Core and Builtins Library ------- +- Issue #18787: spwd.getspnam() now raises a PermissionError if the user + doesn't have privileges. + - Issue #26560: Avoid potential ValueError in BaseHandler.start_response. Initial patch by Peter Inglesby. diff --git a/Modules/spwdmodule.c b/Modules/spwdmodule.c index 49324d50f83..e715d01b647 100644 --- a/Modules/spwdmodule.c +++ b/Modules/spwdmodule.c @@ -137,7 +137,10 @@ spwd_getspnam_impl(PyModuleDef *module, PyObject *arg) if (PyBytes_AsStringAndSize(bytes, &name, NULL) == -1) goto out; if ((p = getspnam(name)) == NULL) { - PyErr_SetString(PyExc_KeyError, "getspnam(): name not found"); + if (errno != 0) + PyErr_SetFromErrno(PyExc_OSError); + else + PyErr_SetString(PyExc_KeyError, "getspnam(): name not found"); goto out; } retval = mkspent(p);