summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2013-04-04 11:32:51 -0400
committerJakub Hrozek <jhrozek@redhat.com>2013-04-05 17:13:06 +0200
commitbdf63b2c329f12b4cdfcc04122f4547aad6bfa35 (patch)
tree0ecc6a5ad95347c04fb118cff4cc64ab019b8e68
parente9c41ad5c89fc7e6c34434c4153753f0b11650ed (diff)
downloadsssd2-bdf63b2c329f12b4cdfcc04122f4547aad6bfa35.tar.gz
sssd2-bdf63b2c329f12b4cdfcc04122f4547aad6bfa35.tar.xz
sssd2-bdf63b2c329f12b4cdfcc04122f4547aad6bfa35.zip
Further restrict become_user drop of privileges.
We never need to regain root after we call become_user() so tighten up even further our privilege drop. Add a setgroups() call to remove all secondary groups root may have been given for whateve reason. Then use the setres[ug]id function to also drop the saved uid/gid so the process cannot regain back root id. Capabilities are also implicitly dropped here, no more CAP_SETUID so this is a Point of No Return, once changed to non-root the process can't get back. Remove redefinition of sys/types.h and unistd.h, they are already defined in util.h and they need to be included after _GNU_SOURCE/_BSD_SOURCE is defined or the prototypes for setres[ug]id will not be found. Add grp.h after util.h for the same reason.
-rw-r--r--src/providers/krb5/krb5_become_user.c33
1 files changed, 18 insertions, 15 deletions
diff --git a/src/providers/krb5/krb5_become_user.c b/src/providers/krb5/krb5_become_user.c
index 082d1415..70bc5630 100644
--- a/src/providers/krb5/krb5_become_user.c
+++ b/src/providers/krb5/krb5_become_user.c
@@ -22,45 +22,48 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <sys/types.h>
-#include <unistd.h>
-
#include "util/util.h"
+#include <grp.h>
errno_t become_user(uid_t uid, gid_t gid)
{
+ uid_t cuid;
int ret;
DEBUG(SSSDBG_FUNC_DATA, ("Trying to become user [%d][%d].\n", uid, gid));
- ret = setgid(gid);
- if (ret == -1) {
- ret = errno;
- DEBUG(SSSDBG_CRIT_FAILURE,
- ("setgid failed [%d][%s].\n", ret, strerror(ret)));
- return ret;
+
+ /* skip call if we already are the requested user */
+ cuid = geteuid();
+ if (uid == cuid) {
+ DEBUG(SSSDBG_FUNC_DATA, ("Already user [%d].\n", uid));
+ return EOK;
}
- ret = setuid(uid);
+ /* drop supplmentary groups first */
+ ret = setgroups(0, NULL);
if (ret == -1) {
ret = errno;
DEBUG(SSSDBG_CRIT_FAILURE,
- ("setuid failed [%d][%s].\n", ret, strerror(ret)));
+ ("setgroups failed [%d][%s].\n", ret, strerror(ret)));
return ret;
}
- ret = setegid(gid);
+ /* change gid so that root cannot be regained (changes saved gid too) */
+ ret = setresgid(gid, gid, gid);
if (ret == -1) {
ret = errno;
DEBUG(SSSDBG_CRIT_FAILURE,
- ("setegid failed [%d][%s].\n", ret, strerror(ret)));
+ ("setresgid failed [%d][%s].\n", ret, strerror(ret)));
return ret;
}
- ret = seteuid(uid);
+ /* change uid so that root cannot be regained (changes saved uid too) */
+ /* this call also takes care of dropping CAP_SETUID, so this is a PNR */
+ ret = setresuid(uid, uid, uid);
if (ret == -1) {
ret = errno;
DEBUG(SSSDBG_CRIT_FAILURE,
- ("seteuid failed [%d][%s].\n", ret, strerror(ret)));
+ ("setresuid failed [%d][%s].\n", ret, strerror(ret)));
return ret;
}