/* wydawca - automatic release submission daemon Copyright (C) 2007, 2009-2013 Sergey Poznyakoff Wydawca 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. Wydawca 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 wydawca. If not, see . */ #include "wydawca.h" int wydawca_userprivs(uid_t uid, gid_t gid, gid_t * grplist, size_t ngrp) { int rc = 0; if (uid == 0) return 0; /* Reset group permissions */ if (geteuid() == 0 && setgroups(ngrp, grplist)) { wy_log(LOG_CRIT, "setgroups(%lu, %lu...): %s", (unsigned long)ngrp, (unsigned long)grplist[0], strerror(errno)); return rc; } /* Switch to the user's gid. On some OSes the effective gid must be reset first */ #if defined(HAVE_SETEGID) if ((rc = setegid(gid)) < 0) wy_log(LOG_CRIT, "setegid(%lu): %s", (unsigned long)gid, strerror(errno)); #elif defined(HAVE_SETREGID) if ((rc = setregid(gid, gid)) < 0) wy_log(LOG_CRIT, "setregid(%lu,%lu)d: %s", (unsigned long)gid, (unsigned long)gid, strerror(errno)); #elif defined(HAVE_SETRESGID) if ((rc = setresgid(gid, gid, gid)) < 0) wy_log(LOG_CRIT, "setresgid(%lu,%lu,%lu): %s", (unsigned long)gid, (unsigned long)gid, (unsigned long)gid, strerror(errno)); #endif if (rc == 0 && gid != 0) { if ((rc = setgid(gid)) < 0 && getegid() != gid) wy_log(LOG_CRIT, "setgid(%lu): %s", (unsigned long)gid, strerror(errno)); if (rc == 0 && getegid() != gid) { wy_log(LOG_CRIT, _("cannot set effective gid to %lu"), (unsigned long)gid); rc = 1; } } /* Now reset uid */ if (rc == 0 && uid != 0) { uid_t euid; if (setuid(uid) || geteuid() != uid || (getuid() != uid && (geteuid() == 0 || getuid() == 0))) { #if defined(HAVE_SETREUID) if (geteuid() != uid) { if (setreuid(uid, -1) < 0) { wy_log(LOG_CRIT, "setreuid(%lu,-1): %s", (unsigned long)uid, strerror(errno)); rc = 1; } if (setuid(uid) < 0) { wy_log(LOG_CRIT, "setreuid(%lu,-1): %s", (unsigned long)uid, strerror(errno)); rc = 1; } } else #endif { wy_log(LOG_CRIT, "setuid(%lu): %s", (unsigned long)uid, strerror(errno)); rc = 1; } } euid = geteuid(); if (uid != 0 && setuid(0) == 0) { wy_log(LOG_CRIT, _("seteuid(0) succeeded when it should not")); rc = 1; } else if (uid != euid && setuid(euid) == 0) { wy_log(LOG_CRIT, _("cannot drop non-root setuid privileges")); rc = 1; } } return rc; }