From bd14b3a8a9731e644a50c1c350b7f76038c22bbb Mon Sep 17 00:00:00 2001 From: "J. Konrad Tegtmeier-Rottach" Date: Mon, 19 Jun 2017 23:13:34 +0200 Subject: [PATCH] Honor PAM's ambient supplemental groups. When compiled with USE_PAM, prefer a combination of getgroups(3) and getgrouplist(3) for ambient and user groups, respectively, to initgroups(3). This way, groups injected into the PAM environment by means of pam_groups.so aren't ignored. Signed-off-by: J. Konrad Tegtmeier-Rottach --- src/helper/UserSession.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/helper/UserSession.cpp b/src/helper/UserSession.cpp index 587888d7..4b5b8553 100644 --- a/src/helper/UserSession.cpp +++ b/src/helper/UserSession.cpp @@ -116,10 +116,67 @@ namespace SDDM { qCritical() << "setgid(" << pw->pw_gid << ") failed for user: " << username; exit(Auth::HELPER_OTHER_ERROR); } + +#ifdef USE_PAM + + // fetch ambient groups from PAM's environment; + // these are set by modules such as pam_groups.so + int n_pam_groups = getgroups(0, NULL); + gid_t *pam_groups = NULL; + if (n_pam_groups > 0) { + pam_groups = new gid_t[n_pam_groups]; + if ((n_pam_groups = getgroups(n_pam_groups, pam_groups)) == -1) { + qCritical() << "getgroups() failed to fetch supplemental" + << "PAM groups for user:" << username; + exit(Auth::HELPER_OTHER_ERROR); + } + } else { + n_pam_groups = 0; + } + + // fetch session's user's groups + int n_user_groups = 0; + gid_t *user_groups = NULL; + if (-1 == getgrouplist(username.constData(), pw->pw_gid, + NULL, &n_user_groups)) { + user_groups = new gid_t[n_user_groups]; + if ((n_user_groups = getgrouplist(username.constData(), + pw->pw_gid, user_groups, + &n_user_groups)) == -1 ) { + qCritical() << "getgrouplist(" << username << ", " << pw->pw_gid + << ") failed"; + exit(Auth::HELPER_OTHER_ERROR); + } + } + + // set groups to concatenation of PAM's ambient + // groups and the session's user's groups + int n_groups = n_pam_groups + n_user_groups; + if (n_groups > 0) { + gid_t *groups = new gid_t[n_groups]; + memcpy(groups, pam_groups, (n_pam_groups * sizeof(gid_t))); + memcpy((groups + n_pam_groups), user_groups, + (n_user_groups * sizeof(gid_t))); + + // setgroups(2) handles duplicate groups + if (setgroups(n_groups, groups) != 0) { + qCritical() << "setgroups() failed for user: " << username; + exit (Auth::HELPER_OTHER_ERROR); + } + delete[] groups; + } + delete[] pam_groups; + delete[] user_groups; + +#else + if (initgroups(pw->pw_name, pw->pw_gid) != 0) { qCritical() << "initgroups(" << pw->pw_name << ", " << pw->pw_gid << ") failed for user: " << username; exit(Auth::HELPER_OTHER_ERROR); } + +#endif /* USE_PAM */ + if (setuid(pw->pw_uid) != 0) { qCritical() << "setuid(" << pw->pw_uid << ") failed for user: " << username; exit(Auth::HELPER_OTHER_ERROR);