aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2008-01-12 15:32:32 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2008-01-12 15:32:32 +0000
commit7fec55752e2b2443bb570d62b288ae06dc1976ed (patch)
tree7abdc77dad1fd7081d6f38303644283a2c52170e
parent2c5d121399c8f075522c349ecf6ca0b70cbef764 (diff)
downloadmailfromd-7fec55752e2b2443bb570d62b288ae06dc1976ed.tar.gz
mailfromd-7fec55752e2b2443bb570d62b288ae06dc1976ed.tar.bz2
* lib/libmf.h: Add switch_to_privs.
* lib/userprivs.c: New file. * lib/Makefile.am: Add userprivs.c. * src/gram.y (time_multiplier): Remove forward dcl. * src/main.c: Move switch_to_privs to lib. git-svn-id: file:///svnroot/mailfromd/branches/gmach@1559 7a8a7f39-df28-0410-adc6-e0d955640f24
-rw-r--r--lib/Makefile.am1
-rw-r--r--lib/libmf.h5
-rw-r--r--lib/userprivs.c150
-rw-r--r--src/gram.y1
-rw-r--r--src/main.c119
5 files changed, 158 insertions, 118 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index af44f802..63a922bc 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -25,6 +25,7 @@ libmf_a_SOURCES=\
dict.c\
nls.c\
parsetime.c\
+ userprivs.c\
version.c
libmf_a_LIBADD=$(LIBOBJS) $(BUILD_SYSLOG_ASYNC)
diff --git a/lib/libmf.h b/lib/libmf.h
index 9cc68889..c5e43cf3 100644
--- a/lib/libmf.h
+++ b/lib/libmf.h
@@ -16,6 +16,9 @@
#include <gettext.h>
#include <mailutils/types.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
#define _(String) gettext(String)
#define N_(String) String
@@ -28,4 +31,6 @@ void dict_init(mu_assoc_t *dict);
char *dict_install(mu_assoc_t dict, const char *name, const char *value);
void dict_destroy(mu_assoc_t *dict);
char *dict_getsym(void *data, const char *str);
+int switch_to_privs (uid_t uid, gid_t gid, mu_list_t retain_groups);
+
diff --git a/lib/userprivs.c b/lib/userprivs.c
new file mode 100644
index 00000000..125210e4
--- /dev/null
+++ b/lib/userprivs.c
@@ -0,0 +1,150 @@
+/* This file is part of mailfromd.
+ Copyright (C) 2007, 2008 Sergey Poznyakoff
+
+ This program 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, or (at your option)
+ any later version.
+
+ This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#include <mailutils/assoc.h>
+#include <mailutils/errno.h>
+#include <mailutils/error.h>
+#include <mailutils/errno.h>
+#include <mailutils/nls.h>
+#include <mailutils/list.h>
+#include <mailutils/iterator.h>
+#include <xalloc.h>
+
+/* Switch to the given UID/GID */
+int
+switch_to_privs (uid_t uid, gid_t gid, mu_list_t retain_groups)
+{
+ int rc = 0;
+ gid_t *emptygidset;
+ size_t size = 1, j = 1;
+ mu_iterator_t itr;
+
+ if (uid == 0) {
+ mu_error(_("Refusing to run as root"));
+ return 1;
+ }
+
+ /* Create a list of supplementary groups */
+ mu_list_count (retain_groups, &size);
+ size++;
+ emptygidset = xmalloc (size * sizeof emptygidset[0]);
+ emptygidset[0] = gid ? gid : getegid();
+
+ if (mu_list_get_iterator(retain_groups, &itr) == 0) {
+ for (mu_iterator_first (itr);
+ !mu_iterator_is_done (itr); mu_iterator_next (itr))
+ mu_iterator_current (itr,
+ (void **)(emptygidset + j++));
+ mu_iterator_destroy(&itr);
+ }
+
+ /* Reset group permissions */
+ if (geteuid() == 0 && setgroups(j, emptygidset)) {
+ mu_error(_("setgroups(1, %lu) failed: %s"),
+ (unsigned long) emptygidset[0],
+ mu_strerror(errno));
+ rc = 1;
+ }
+ free(emptygidset);
+
+ /* 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)
+ mu_error(_("setegid(%lu) failed: %s"),
+ (unsigned long) gid, mu_strerror(errno));
+#elif defined(HAVE_SETREGID)
+ if ((rc = setregid(gid, gid)) < 0)
+ mu_error(_("setregid(%lu,%lu) failed: %s"),
+ (unsigned long) gid, (unsigned long) gid,
+ mu_strerror(errno));
+#elif defined(HAVE_SETRESGID)
+ if ((rc = setresgid(gid, gid, gid)) < 0)
+ mu_error(_("setresgid(%lu,%lu,%lu) failed: %s"),
+ (unsigned long) gid,
+ (unsigned long) gid,
+ (unsigned long) gid,
+ mu_strerror(errno));
+#endif
+
+ if (rc == 0 && gid != 0) {
+ if ((rc = setgid(gid)) < 0 && getegid() != gid)
+ mu_error(_("setgid(%lu) failed: %s"),
+ (unsigned long) gid, mu_strerror(errno));
+ if (rc == 0 && getegid() != gid) {
+ mu_error(_("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) {
+ mu_error(_("setreuid(%lu,-1) failed: %s"),
+ (unsigned long) uid,
+ mu_strerror(errno));
+ rc = 1;
+ }
+ if (setuid(uid) < 0) {
+ mu_error(_("second setuid(%lu) failed: %s"),
+ (unsigned long) uid,
+ mu_strerror(errno));
+ rc = 1;
+ }
+ } else
+#endif
+ {
+ mu_error(_("setuid(%lu) failed: %s"),
+ (unsigned long) uid,
+ mu_strerror(errno));
+ rc = 1;
+ }
+ }
+
+ euid = geteuid();
+ if (uid != 0 && setuid(0) == 0) {
+ mu_error(_("seteuid(0) succeeded when it should not"));
+ rc = 1;
+ } else if (uid != euid && setuid(euid) == 0) {
+ mu_error(_("Cannot drop non-root setuid privileges"));
+ rc = 1;
+ }
+
+ }
+
+ return rc;
+}
+
+
diff --git a/src/gram.y b/src/gram.y
index a3bbac19..a456c2e8 100644
--- a/src/gram.y
+++ b/src/gram.y
@@ -33,7 +33,6 @@
static NODE *alloc_node(enum node_type type, const struct locus *locus);
static void free_node(NODE *node);
static void set_poll_arg(struct poll_data *poll, int kw, NODE *expr);
-static int time_multiplier(const char *, unsigned *, unsigned *);
static int codegen(prog_counter_t *pc, NODE *node, int finalize,
size_t nautos);
static void mark(NODE *node);
diff --git a/src/main.c b/src/main.c
index e2416989..201b891c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1633,122 +1633,6 @@ struct mu_cfg_param mf_cfg_param[] = {
/* Auxiliary functions */
-/* Switch to the given UID/GID */
-int
-switch_to_privs(uid_t uid, gid_t gid)
-{
- int rc = 0;
- gid_t *emptygidset;
- size_t size = 1, j = 1;
- mu_iterator_t itr;
-
- if (uid == 0) {
- mu_error(_("Refusing to run as root"));
- return 1;
- }
-
- /* Create a list of supplementary groups */
- mu_list_count (retain_groups, &size);
- size++;
- emptygidset = xmalloc (size * sizeof emptygidset[0]);
- emptygidset[0] = gid ? gid : getegid();
-
- if (mu_list_get_iterator(retain_groups, &itr) == 0) {
- for (mu_iterator_first (itr);
- !mu_iterator_is_done (itr); mu_iterator_next (itr))
- mu_iterator_current (itr,
- (void **)(emptygidset + j++));
- mu_iterator_destroy(&itr);
- }
-
- /* Reset group permissions */
- if (geteuid() == 0 && setgroups(j, emptygidset)) {
- mu_error(_("setgroups(1, %lu) failed: %s"),
- (unsigned long) emptygidset[0],
- mu_strerror(errno));
- rc = 1;
- }
- free(emptygidset);
-
- /* 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)
- mu_error(_("setegid(%lu) failed: %s"),
- (unsigned long) gid, mu_strerror(errno));
-#elif defined(HAVE_SETREGID)
- if ((rc = setregid(gid, gid)) < 0)
- mu_error(_("setregid(%lu,%lu) failed: %s"),
- (unsigned long) gid, (unsigned long) gid,
- mu_strerror(errno));
-#elif defined(HAVE_SETRESGID)
- if ((rc = setresgid(gid, gid, gid)) < 0)
- mu_error(_("setresgid(%lu,%lu,%lu) failed: %s"),
- (unsigned long) gid,
- (unsigned long) gid,
- (unsigned long) gid,
- mu_strerror(errno));
-#endif
-
- if (rc == 0 && gid != 0) {
- if ((rc = setgid(gid)) < 0 && getegid() != gid)
- mu_error(_("setgid(%lu) failed: %s"),
- (unsigned long) gid, mu_strerror(errno));
- if (rc == 0 && getegid() != gid) {
- mu_error(_("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) {
- mu_error(_("setreuid(%lu,-1) failed: %s"),
- (unsigned long) uid,
- mu_strerror(errno));
- rc = 1;
- }
- if (setuid(uid) < 0) {
- mu_error(_("second setuid(%lu) failed: %s"),
- (unsigned long) uid,
- mu_strerror(errno));
- rc = 1;
- }
- } else
-#endif
- {
- mu_error(_("setuid(%lu) failed: %s"),
- (unsigned long) uid,
- mu_strerror(errno));
- rc = 1;
- }
- }
-
- euid = geteuid();
- if (uid != 0 && setuid(0) == 0) {
- mu_error(_("seteuid(0) succeeded when it should not"));
- rc = 1;
- } else if (uid != euid && setuid(euid) == 0) {
- mu_error(_("Cannot drop non-root setuid privileges"));
- rc = 1;
- }
-
- }
-
- return rc;
-}
-
void
priv_setup()
{
@@ -1762,7 +1646,8 @@ priv_setup()
mu_error(_("No such user: %s"), user);
exit(EX_SOFTWARE);
}
- if (pw && switch_to_privs(pw->pw_uid, pw->pw_gid))
+ if (pw && switch_to_privs(pw->pw_uid, pw->pw_gid,
+ retain_groups))
exit(EX_SOFTWARE);
}
}

Return to:

Send suggestions and report system problems to the System administrator.