17db96d56Sopenharmony_ci 27db96d56Sopenharmony_ci/* UNIX password file access module */ 37db96d56Sopenharmony_ci 47db96d56Sopenharmony_ci#include "Python.h" 57db96d56Sopenharmony_ci#include "posixmodule.h" 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ci#include <pwd.h> 87db96d56Sopenharmony_ci 97db96d56Sopenharmony_ci#include "clinic/pwdmodule.c.h" 107db96d56Sopenharmony_ci/*[clinic input] 117db96d56Sopenharmony_cimodule pwd 127db96d56Sopenharmony_ci[clinic start generated code]*/ 137db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=60f628ef356b97b6]*/ 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_cistatic PyStructSequence_Field struct_pwd_type_fields[] = { 167db96d56Sopenharmony_ci {"pw_name", "user name"}, 177db96d56Sopenharmony_ci {"pw_passwd", "password"}, 187db96d56Sopenharmony_ci {"pw_uid", "user id"}, 197db96d56Sopenharmony_ci {"pw_gid", "group id"}, 207db96d56Sopenharmony_ci {"pw_gecos", "real name"}, 217db96d56Sopenharmony_ci {"pw_dir", "home directory"}, 227db96d56Sopenharmony_ci {"pw_shell", "shell program"}, 237db96d56Sopenharmony_ci {0} 247db96d56Sopenharmony_ci}; 257db96d56Sopenharmony_ci 267db96d56Sopenharmony_ciPyDoc_STRVAR(struct_passwd__doc__, 277db96d56Sopenharmony_ci"pwd.struct_passwd: Results from getpw*() routines.\n\n\ 287db96d56Sopenharmony_ciThis object may be accessed either as a tuple of\n\ 297db96d56Sopenharmony_ci (pw_name,pw_passwd,pw_uid,pw_gid,pw_gecos,pw_dir,pw_shell)\n\ 307db96d56Sopenharmony_cior via the object attributes as named in the above tuple."); 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_cistatic PyStructSequence_Desc struct_pwd_type_desc = { 337db96d56Sopenharmony_ci "pwd.struct_passwd", 347db96d56Sopenharmony_ci struct_passwd__doc__, 357db96d56Sopenharmony_ci struct_pwd_type_fields, 367db96d56Sopenharmony_ci 7, 377db96d56Sopenharmony_ci}; 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_ciPyDoc_STRVAR(pwd__doc__, 407db96d56Sopenharmony_ci"This module provides access to the Unix password database.\n\ 417db96d56Sopenharmony_ciIt is available on all Unix versions.\n\ 427db96d56Sopenharmony_ci\n\ 437db96d56Sopenharmony_ciPassword database entries are reported as 7-tuples containing the following\n\ 447db96d56Sopenharmony_ciitems from the password database (see `<pwd.h>'), in order:\n\ 457db96d56Sopenharmony_cipw_name, pw_passwd, pw_uid, pw_gid, pw_gecos, pw_dir, pw_shell.\n\ 467db96d56Sopenharmony_ciThe uid and gid items are integers, all others are strings. An\n\ 477db96d56Sopenharmony_ciexception is raised if the entry asked for cannot be found."); 487db96d56Sopenharmony_ci 497db96d56Sopenharmony_ci 507db96d56Sopenharmony_citypedef struct { 517db96d56Sopenharmony_ci PyTypeObject *StructPwdType; 527db96d56Sopenharmony_ci} pwdmodulestate; 537db96d56Sopenharmony_ci 547db96d56Sopenharmony_cistatic inline pwdmodulestate* 557db96d56Sopenharmony_ciget_pwd_state(PyObject *module) 567db96d56Sopenharmony_ci{ 577db96d56Sopenharmony_ci void *state = PyModule_GetState(module); 587db96d56Sopenharmony_ci assert(state != NULL); 597db96d56Sopenharmony_ci return (pwdmodulestate *)state; 607db96d56Sopenharmony_ci} 617db96d56Sopenharmony_ci 627db96d56Sopenharmony_cistatic struct PyModuleDef pwdmodule; 637db96d56Sopenharmony_ci 647db96d56Sopenharmony_ci#define DEFAULT_BUFFER_SIZE 1024 657db96d56Sopenharmony_ci 667db96d56Sopenharmony_cistatic void 677db96d56Sopenharmony_cisets(PyObject *v, int i, const char* val) 687db96d56Sopenharmony_ci{ 697db96d56Sopenharmony_ci if (val) { 707db96d56Sopenharmony_ci PyObject *o = PyUnicode_DecodeFSDefault(val); 717db96d56Sopenharmony_ci PyStructSequence_SET_ITEM(v, i, o); 727db96d56Sopenharmony_ci } 737db96d56Sopenharmony_ci else { 747db96d56Sopenharmony_ci PyStructSequence_SET_ITEM(v, i, Py_None); 757db96d56Sopenharmony_ci Py_INCREF(Py_None); 767db96d56Sopenharmony_ci } 777db96d56Sopenharmony_ci} 787db96d56Sopenharmony_ci 797db96d56Sopenharmony_cistatic PyObject * 807db96d56Sopenharmony_cimkpwent(PyObject *module, struct passwd *p) 817db96d56Sopenharmony_ci{ 827db96d56Sopenharmony_ci int setIndex = 0; 837db96d56Sopenharmony_ci PyObject *v = PyStructSequence_New(get_pwd_state(module)->StructPwdType); 847db96d56Sopenharmony_ci if (v == NULL) 857db96d56Sopenharmony_ci return NULL; 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_ci#define SETS(i,val) sets(v, i, val) 887db96d56Sopenharmony_ci 897db96d56Sopenharmony_ci SETS(setIndex++, p->pw_name); 907db96d56Sopenharmony_ci#if defined(HAVE_STRUCT_PASSWD_PW_PASSWD) && !defined(__ANDROID__) 917db96d56Sopenharmony_ci SETS(setIndex++, p->pw_passwd); 927db96d56Sopenharmony_ci#else 937db96d56Sopenharmony_ci SETS(setIndex++, ""); 947db96d56Sopenharmony_ci#endif 957db96d56Sopenharmony_ci PyStructSequence_SET_ITEM(v, setIndex++, _PyLong_FromUid(p->pw_uid)); 967db96d56Sopenharmony_ci PyStructSequence_SET_ITEM(v, setIndex++, _PyLong_FromGid(p->pw_gid)); 977db96d56Sopenharmony_ci#if defined(HAVE_STRUCT_PASSWD_PW_GECOS) 987db96d56Sopenharmony_ci SETS(setIndex++, p->pw_gecos); 997db96d56Sopenharmony_ci#else 1007db96d56Sopenharmony_ci SETS(setIndex++, ""); 1017db96d56Sopenharmony_ci#endif 1027db96d56Sopenharmony_ci SETS(setIndex++, p->pw_dir); 1037db96d56Sopenharmony_ci SETS(setIndex++, p->pw_shell); 1047db96d56Sopenharmony_ci 1057db96d56Sopenharmony_ci#undef SETS 1067db96d56Sopenharmony_ci 1077db96d56Sopenharmony_ci if (PyErr_Occurred()) { 1087db96d56Sopenharmony_ci Py_XDECREF(v); 1097db96d56Sopenharmony_ci return NULL; 1107db96d56Sopenharmony_ci } 1117db96d56Sopenharmony_ci 1127db96d56Sopenharmony_ci return v; 1137db96d56Sopenharmony_ci} 1147db96d56Sopenharmony_ci 1157db96d56Sopenharmony_ci/*[clinic input] 1167db96d56Sopenharmony_cipwd.getpwuid 1177db96d56Sopenharmony_ci 1187db96d56Sopenharmony_ci uidobj: object 1197db96d56Sopenharmony_ci / 1207db96d56Sopenharmony_ci 1217db96d56Sopenharmony_ciReturn the password database entry for the given numeric user ID. 1227db96d56Sopenharmony_ci 1237db96d56Sopenharmony_ciSee `help(pwd)` for more on password database entries. 1247db96d56Sopenharmony_ci[clinic start generated code]*/ 1257db96d56Sopenharmony_ci 1267db96d56Sopenharmony_cistatic PyObject * 1277db96d56Sopenharmony_cipwd_getpwuid(PyObject *module, PyObject *uidobj) 1287db96d56Sopenharmony_ci/*[clinic end generated code: output=c4ee1d4d429b86c4 input=ae64d507a1c6d3e8]*/ 1297db96d56Sopenharmony_ci{ 1307db96d56Sopenharmony_ci PyObject *retval = NULL; 1317db96d56Sopenharmony_ci uid_t uid; 1327db96d56Sopenharmony_ci int nomem = 0; 1337db96d56Sopenharmony_ci struct passwd *p; 1347db96d56Sopenharmony_ci char *buf = NULL, *buf2 = NULL; 1357db96d56Sopenharmony_ci 1367db96d56Sopenharmony_ci if (!_Py_Uid_Converter(uidobj, &uid)) { 1377db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_OverflowError)) 1387db96d56Sopenharmony_ci PyErr_Format(PyExc_KeyError, 1397db96d56Sopenharmony_ci "getpwuid(): uid not found"); 1407db96d56Sopenharmony_ci return NULL; 1417db96d56Sopenharmony_ci } 1427db96d56Sopenharmony_ci#ifdef HAVE_GETPWUID_R 1437db96d56Sopenharmony_ci int status; 1447db96d56Sopenharmony_ci Py_ssize_t bufsize; 1457db96d56Sopenharmony_ci /* Note: 'pwd' will be used via pointer 'p' on getpwuid_r success. */ 1467db96d56Sopenharmony_ci struct passwd pwd; 1477db96d56Sopenharmony_ci 1487db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 1497db96d56Sopenharmony_ci bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); 1507db96d56Sopenharmony_ci if (bufsize == -1) { 1517db96d56Sopenharmony_ci bufsize = DEFAULT_BUFFER_SIZE; 1527db96d56Sopenharmony_ci } 1537db96d56Sopenharmony_ci 1547db96d56Sopenharmony_ci while(1) { 1557db96d56Sopenharmony_ci buf2 = PyMem_RawRealloc(buf, bufsize); 1567db96d56Sopenharmony_ci if (buf2 == NULL) { 1577db96d56Sopenharmony_ci p = NULL; 1587db96d56Sopenharmony_ci nomem = 1; 1597db96d56Sopenharmony_ci break; 1607db96d56Sopenharmony_ci } 1617db96d56Sopenharmony_ci buf = buf2; 1627db96d56Sopenharmony_ci status = getpwuid_r(uid, &pwd, buf, bufsize, &p); 1637db96d56Sopenharmony_ci if (status != 0) { 1647db96d56Sopenharmony_ci p = NULL; 1657db96d56Sopenharmony_ci } 1667db96d56Sopenharmony_ci if (p != NULL || status != ERANGE) { 1677db96d56Sopenharmony_ci break; 1687db96d56Sopenharmony_ci } 1697db96d56Sopenharmony_ci if (bufsize > (PY_SSIZE_T_MAX >> 1)) { 1707db96d56Sopenharmony_ci nomem = 1; 1717db96d56Sopenharmony_ci break; 1727db96d56Sopenharmony_ci } 1737db96d56Sopenharmony_ci bufsize <<= 1; 1747db96d56Sopenharmony_ci } 1757db96d56Sopenharmony_ci 1767db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 1777db96d56Sopenharmony_ci#else 1787db96d56Sopenharmony_ci p = getpwuid(uid); 1797db96d56Sopenharmony_ci#endif 1807db96d56Sopenharmony_ci if (p == NULL) { 1817db96d56Sopenharmony_ci PyMem_RawFree(buf); 1827db96d56Sopenharmony_ci if (nomem == 1) { 1837db96d56Sopenharmony_ci return PyErr_NoMemory(); 1847db96d56Sopenharmony_ci } 1857db96d56Sopenharmony_ci PyObject *uid_obj = _PyLong_FromUid(uid); 1867db96d56Sopenharmony_ci if (uid_obj == NULL) 1877db96d56Sopenharmony_ci return NULL; 1887db96d56Sopenharmony_ci PyErr_Format(PyExc_KeyError, 1897db96d56Sopenharmony_ci "getpwuid(): uid not found: %S", uid_obj); 1907db96d56Sopenharmony_ci Py_DECREF(uid_obj); 1917db96d56Sopenharmony_ci return NULL; 1927db96d56Sopenharmony_ci } 1937db96d56Sopenharmony_ci retval = mkpwent(module, p); 1947db96d56Sopenharmony_ci#ifdef HAVE_GETPWUID_R 1957db96d56Sopenharmony_ci PyMem_RawFree(buf); 1967db96d56Sopenharmony_ci#endif 1977db96d56Sopenharmony_ci return retval; 1987db96d56Sopenharmony_ci} 1997db96d56Sopenharmony_ci 2007db96d56Sopenharmony_ci/*[clinic input] 2017db96d56Sopenharmony_cipwd.getpwnam 2027db96d56Sopenharmony_ci 2037db96d56Sopenharmony_ci name: unicode 2047db96d56Sopenharmony_ci / 2057db96d56Sopenharmony_ci 2067db96d56Sopenharmony_ciReturn the password database entry for the given user name. 2077db96d56Sopenharmony_ci 2087db96d56Sopenharmony_ciSee `help(pwd)` for more on password database entries. 2097db96d56Sopenharmony_ci[clinic start generated code]*/ 2107db96d56Sopenharmony_ci 2117db96d56Sopenharmony_cistatic PyObject * 2127db96d56Sopenharmony_cipwd_getpwnam_impl(PyObject *module, PyObject *name) 2137db96d56Sopenharmony_ci/*[clinic end generated code: output=359ce1ddeb7a824f input=a6aeb5e3447fb9e0]*/ 2147db96d56Sopenharmony_ci{ 2157db96d56Sopenharmony_ci char *buf = NULL, *buf2 = NULL, *name_chars; 2167db96d56Sopenharmony_ci int nomem = 0; 2177db96d56Sopenharmony_ci struct passwd *p; 2187db96d56Sopenharmony_ci PyObject *bytes, *retval = NULL; 2197db96d56Sopenharmony_ci 2207db96d56Sopenharmony_ci if ((bytes = PyUnicode_EncodeFSDefault(name)) == NULL) 2217db96d56Sopenharmony_ci return NULL; 2227db96d56Sopenharmony_ci /* check for embedded null bytes */ 2237db96d56Sopenharmony_ci if (PyBytes_AsStringAndSize(bytes, &name_chars, NULL) == -1) 2247db96d56Sopenharmony_ci goto out; 2257db96d56Sopenharmony_ci#ifdef HAVE_GETPWNAM_R 2267db96d56Sopenharmony_ci int status; 2277db96d56Sopenharmony_ci Py_ssize_t bufsize; 2287db96d56Sopenharmony_ci /* Note: 'pwd' will be used via pointer 'p' on getpwnam_r success. */ 2297db96d56Sopenharmony_ci struct passwd pwd; 2307db96d56Sopenharmony_ci 2317db96d56Sopenharmony_ci Py_BEGIN_ALLOW_THREADS 2327db96d56Sopenharmony_ci bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); 2337db96d56Sopenharmony_ci if (bufsize == -1) { 2347db96d56Sopenharmony_ci bufsize = DEFAULT_BUFFER_SIZE; 2357db96d56Sopenharmony_ci } 2367db96d56Sopenharmony_ci 2377db96d56Sopenharmony_ci while(1) { 2387db96d56Sopenharmony_ci buf2 = PyMem_RawRealloc(buf, bufsize); 2397db96d56Sopenharmony_ci if (buf2 == NULL) { 2407db96d56Sopenharmony_ci p = NULL; 2417db96d56Sopenharmony_ci nomem = 1; 2427db96d56Sopenharmony_ci break; 2437db96d56Sopenharmony_ci } 2447db96d56Sopenharmony_ci buf = buf2; 2457db96d56Sopenharmony_ci status = getpwnam_r(name_chars, &pwd, buf, bufsize, &p); 2467db96d56Sopenharmony_ci if (status != 0) { 2477db96d56Sopenharmony_ci p = NULL; 2487db96d56Sopenharmony_ci } 2497db96d56Sopenharmony_ci if (p != NULL || status != ERANGE) { 2507db96d56Sopenharmony_ci break; 2517db96d56Sopenharmony_ci } 2527db96d56Sopenharmony_ci if (bufsize > (PY_SSIZE_T_MAX >> 1)) { 2537db96d56Sopenharmony_ci nomem = 1; 2547db96d56Sopenharmony_ci break; 2557db96d56Sopenharmony_ci } 2567db96d56Sopenharmony_ci bufsize <<= 1; 2577db96d56Sopenharmony_ci } 2587db96d56Sopenharmony_ci 2597db96d56Sopenharmony_ci Py_END_ALLOW_THREADS 2607db96d56Sopenharmony_ci#else 2617db96d56Sopenharmony_ci p = getpwnam(name_chars); 2627db96d56Sopenharmony_ci#endif 2637db96d56Sopenharmony_ci if (p == NULL) { 2647db96d56Sopenharmony_ci if (nomem == 1) { 2657db96d56Sopenharmony_ci PyErr_NoMemory(); 2667db96d56Sopenharmony_ci } 2677db96d56Sopenharmony_ci else { 2687db96d56Sopenharmony_ci PyErr_Format(PyExc_KeyError, 2697db96d56Sopenharmony_ci "getpwnam(): name not found: %R", name); 2707db96d56Sopenharmony_ci } 2717db96d56Sopenharmony_ci goto out; 2727db96d56Sopenharmony_ci } 2737db96d56Sopenharmony_ci retval = mkpwent(module, p); 2747db96d56Sopenharmony_ciout: 2757db96d56Sopenharmony_ci PyMem_RawFree(buf); 2767db96d56Sopenharmony_ci Py_DECREF(bytes); 2777db96d56Sopenharmony_ci return retval; 2787db96d56Sopenharmony_ci} 2797db96d56Sopenharmony_ci 2807db96d56Sopenharmony_ci#ifdef HAVE_GETPWENT 2817db96d56Sopenharmony_ci/*[clinic input] 2827db96d56Sopenharmony_cipwd.getpwall 2837db96d56Sopenharmony_ci 2847db96d56Sopenharmony_ciReturn a list of all available password database entries, in arbitrary order. 2857db96d56Sopenharmony_ci 2867db96d56Sopenharmony_ciSee help(pwd) for more on password database entries. 2877db96d56Sopenharmony_ci[clinic start generated code]*/ 2887db96d56Sopenharmony_ci 2897db96d56Sopenharmony_cistatic PyObject * 2907db96d56Sopenharmony_cipwd_getpwall_impl(PyObject *module) 2917db96d56Sopenharmony_ci/*[clinic end generated code: output=4853d2f5a0afac8a input=d7ecebfd90219b85]*/ 2927db96d56Sopenharmony_ci{ 2937db96d56Sopenharmony_ci PyObject *d; 2947db96d56Sopenharmony_ci struct passwd *p; 2957db96d56Sopenharmony_ci if ((d = PyList_New(0)) == NULL) 2967db96d56Sopenharmony_ci return NULL; 2977db96d56Sopenharmony_ci setpwent(); 2987db96d56Sopenharmony_ci while ((p = getpwent()) != NULL) { 2997db96d56Sopenharmony_ci PyObject *v = mkpwent(module, p); 3007db96d56Sopenharmony_ci if (v == NULL || PyList_Append(d, v) != 0) { 3017db96d56Sopenharmony_ci Py_XDECREF(v); 3027db96d56Sopenharmony_ci Py_DECREF(d); 3037db96d56Sopenharmony_ci endpwent(); 3047db96d56Sopenharmony_ci return NULL; 3057db96d56Sopenharmony_ci } 3067db96d56Sopenharmony_ci Py_DECREF(v); 3077db96d56Sopenharmony_ci } 3087db96d56Sopenharmony_ci endpwent(); 3097db96d56Sopenharmony_ci return d; 3107db96d56Sopenharmony_ci} 3117db96d56Sopenharmony_ci#endif 3127db96d56Sopenharmony_ci 3137db96d56Sopenharmony_cistatic PyMethodDef pwd_methods[] = { 3147db96d56Sopenharmony_ci PWD_GETPWUID_METHODDEF 3157db96d56Sopenharmony_ci PWD_GETPWNAM_METHODDEF 3167db96d56Sopenharmony_ci#ifdef HAVE_GETPWENT 3177db96d56Sopenharmony_ci PWD_GETPWALL_METHODDEF 3187db96d56Sopenharmony_ci#endif 3197db96d56Sopenharmony_ci {NULL, NULL} /* sentinel */ 3207db96d56Sopenharmony_ci}; 3217db96d56Sopenharmony_ci 3227db96d56Sopenharmony_cistatic int 3237db96d56Sopenharmony_cipwdmodule_exec(PyObject *module) 3247db96d56Sopenharmony_ci{ 3257db96d56Sopenharmony_ci pwdmodulestate *state = get_pwd_state(module); 3267db96d56Sopenharmony_ci 3277db96d56Sopenharmony_ci state->StructPwdType = PyStructSequence_NewType(&struct_pwd_type_desc); 3287db96d56Sopenharmony_ci if (state->StructPwdType == NULL) { 3297db96d56Sopenharmony_ci return -1; 3307db96d56Sopenharmony_ci } 3317db96d56Sopenharmony_ci if (PyModule_AddType(module, state->StructPwdType) < 0) { 3327db96d56Sopenharmony_ci return -1; 3337db96d56Sopenharmony_ci } 3347db96d56Sopenharmony_ci return 0; 3357db96d56Sopenharmony_ci} 3367db96d56Sopenharmony_ci 3377db96d56Sopenharmony_cistatic PyModuleDef_Slot pwdmodule_slots[] = { 3387db96d56Sopenharmony_ci {Py_mod_exec, pwdmodule_exec}, 3397db96d56Sopenharmony_ci {0, NULL} 3407db96d56Sopenharmony_ci}; 3417db96d56Sopenharmony_ci 3427db96d56Sopenharmony_cistatic int pwdmodule_traverse(PyObject *m, visitproc visit, void *arg) { 3437db96d56Sopenharmony_ci Py_VISIT(get_pwd_state(m)->StructPwdType); 3447db96d56Sopenharmony_ci return 0; 3457db96d56Sopenharmony_ci} 3467db96d56Sopenharmony_cistatic int pwdmodule_clear(PyObject *m) { 3477db96d56Sopenharmony_ci Py_CLEAR(get_pwd_state(m)->StructPwdType); 3487db96d56Sopenharmony_ci return 0; 3497db96d56Sopenharmony_ci} 3507db96d56Sopenharmony_cistatic void pwdmodule_free(void *m) { 3517db96d56Sopenharmony_ci pwdmodule_clear((PyObject *)m); 3527db96d56Sopenharmony_ci} 3537db96d56Sopenharmony_ci 3547db96d56Sopenharmony_cistatic struct PyModuleDef pwdmodule = { 3557db96d56Sopenharmony_ci PyModuleDef_HEAD_INIT, 3567db96d56Sopenharmony_ci .m_name = "pwd", 3577db96d56Sopenharmony_ci .m_doc = pwd__doc__, 3587db96d56Sopenharmony_ci .m_size = sizeof(pwdmodulestate), 3597db96d56Sopenharmony_ci .m_methods = pwd_methods, 3607db96d56Sopenharmony_ci .m_slots = pwdmodule_slots, 3617db96d56Sopenharmony_ci .m_traverse = pwdmodule_traverse, 3627db96d56Sopenharmony_ci .m_clear = pwdmodule_clear, 3637db96d56Sopenharmony_ci .m_free = pwdmodule_free, 3647db96d56Sopenharmony_ci}; 3657db96d56Sopenharmony_ci 3667db96d56Sopenharmony_ci 3677db96d56Sopenharmony_ciPyMODINIT_FUNC 3687db96d56Sopenharmony_ciPyInit_pwd(void) 3697db96d56Sopenharmony_ci{ 3707db96d56Sopenharmony_ci return PyModuleDef_Init(&pwdmodule); 3717db96d56Sopenharmony_ci} 372