summaryrefslogtreecommitdiffabout
path: root/src/userprivs.c
Side-by-side diff
Diffstat (limited to 'src/userprivs.c') (more/less context) (ignore whitespace changes)
-rw-r--r--src/userprivs.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/src/userprivs.c b/src/userprivs.c
new file mode 100644
index 0000000..e6a18c8
--- a/dev/null
+++ b/src/userprivs.c
@@ -0,0 +1,118 @@
+/* wydawca - automatic release submission daemon
+ Copyright (C) 2007, 2009 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 <http://www.gnu.org/licenses/>. */
+
+#include "wydawca.h"
+
+int
+wydawca_userprivs (uid_t uid, gid_t gid, gid_t *grplist, size_t ngrp)
+{
+ int rc = 0;
+ size_t size = 1, j = 1;
+
+ if (uid == 0)
+ return 0;
+
+ /* Reset group permissions */
+ if (geteuid () == 0 && setgroups (ngrp, grplist))
+ {
+ logmsg (LOG_CRIT, "setgroups(%lu, %lu...): %s",
+ ngrp, grplist[0], 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)
+ logmsg (LOG_CRIT, "setegid(%lu): %s", gid, strerror (errno));
+#elif defined(HAVE_SETREGID)
+ if ((rc = setregid (gid, gid)) < 0)
+ logmsg (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)
+ logmsg (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)
+ logmsg (LOG_CRIT, "setgid(%lu): %s",
+ (unsigned long) gid, strerror (errno));
+ if (rc == 0 && getegid () != gid)
+ {
+ logmsg (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)
+ {
+ logmsg (LOG_CRIT, "setreuid(%lu,-1): %s",
+ (unsigned long) uid, strerror (errno));
+ rc = 1;
+ }
+ if (setuid (uid) < 0)
+ {
+ logmsg (LOG_CRIT, "setreuid(%lu,-1): %s",
+ (unsigned long) uid, strerror (errno));
+ rc = 1;
+ }
+ }
+ else
+#endif
+ {
+ logmsg (LOG_CRIT, "setuid(%lu): %s",
+ (unsigned long) uid, strerror (errno));
+ rc = 1;
+ }
+ }
+
+ euid = geteuid ();
+ if (uid != 0 && setuid (0) == 0)
+ {
+ logmsg (LOG_CRIT, _("seteuid(0) succeeded when it should not"));
+ rc = 1;
+ }
+ else if (uid != euid && setuid (euid) == 0)
+ {
+ logmsg (LOG_CRIT, _("cannot drop non-root setuid privileges"));
+ rc = 1;
+ }
+
+ }
+
+ return rc;
+}

Return to:

Send suggestions and report system problems to the System administrator.