aboutsummaryrefslogtreecommitdiff
path: root/lib/userprivs.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/userprivs.c')
-rw-r--r--lib/userprivs.c291
1 files changed, 0 insertions, 291 deletions
diff --git a/lib/userprivs.c b/lib/userprivs.c
deleted file mode 100644
index 8d13c38..0000000
--- a/lib/userprivs.c
+++ /dev/null
@@ -1,291 +0,0 @@
1/* This file is part of Mailfromd.
2 Copyright (C) 2007, 2008 Sergey Poznyakoff
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
17#ifdef HAVE_CONFIG_H
18# include <config.h>
19#endif
20#include <stdlib.h>
21#include <string.h>
22#include <pwd.h>
23#include <grp.h>
24#include <unistd.h>
25#include <mailutils/assoc.h>
26#include <mailutils/errno.h>
27#include <mailutils/error.h>
28#include <mailutils/errno.h>
29#include <mailutils/nls.h>
30#include <mailutils/list.h>
31#include <mailutils/iterator.h>
32/* FIXME: */
33#include <sysexits.h>
34#include "libpies.h"
35
36int
37get_user_groups (mu_list_t *pgrouplist, const char *user)
38{
39 int rc;
40 struct group *gr;
41 mu_list_t list;
42
43 if (!*pgrouplist)
44 {
45 rc = mu_list_create (pgrouplist);
46 if (rc)
47 {
48 mu_error (_("%s: cannot create list: %s"),
49 "get_user_groups", mu_strerror (rc));
50 return rc;
51 }
52 }
53 list = *pgrouplist;
54 setgrent ();
55 for (rc = 0; rc == 0 && (gr = getgrent ());)
56 {
57 char **p;
58 for (p = gr->gr_mem; *p; p++)
59 if (strcmp (*p, user) == 0)
60 {
61 /* FIXME: Avoid duplicating gids */
62 rc = mu_list_append (list, (void *) gr->gr_gid);
63 if (rc)
64 mu_error (_("%s: cannot append to list: %s"),
65 "get_user_groups", mu_strerror (rc));
66 break;
67 }
68 }
69 endgrent ();
70 return rc;
71}
72
73/* Switch to the given UID/GID */
74int
75switch_to_privs (uid_t uid, gid_t gid, mu_list_t retain_groups)
76{
77 int rc = 0;
78 gid_t *emptygidset;
79 size_t size = 1, j = 1;
80 mu_iterator_t itr;
81
82 if (uid == 0)
83 {
84 mu_error (_("Refusing to run as root"));
85 return 1;
86 }
87
88 /* Create a list of supplementary groups */
89 mu_list_count (retain_groups, &size);
90 size++;
91 emptygidset = xmalloc (size * sizeof emptygidset[0]);
92 emptygidset[0] = gid ? gid : getegid ();
93
94 if (mu_list_get_iterator (retain_groups, &itr) == 0)
95 {
96 for (mu_iterator_first (itr);
97 !mu_iterator_is_done (itr); mu_iterator_next (itr))
98 mu_iterator_current (itr, (void **) (emptygidset + j++));
99 mu_iterator_destroy (&itr);
100 }
101
102 /* Reset group permissions */
103 if (geteuid () == 0 && setgroups (j, emptygidset))
104 {
105 mu_error (_("setgroups(1, %lu) failed: %s"),
106 (unsigned long) emptygidset[0], mu_strerror (errno));
107 rc = 1;
108 }
109 free (emptygidset);
110
111 /* Switch to the user's gid. On some OSes the effective gid must
112 be reset first */
113
114#if defined(HAVE_SETEGID)
115 if ((rc = setegid (gid)) < 0)
116 mu_error (_("setegid(%lu) failed: %s"),
117 (unsigned long) gid, mu_strerror (errno));
118#elif defined(HAVE_SETREGID)
119 if ((rc = setregid (gid, gid)) < 0)
120 mu_error (_("setregid(%lu,%lu) failed: %s"),
121 (unsigned long) gid, (unsigned long) gid, mu_strerror (errno));
122#elif defined(HAVE_SETRESGID)
123 if ((rc = setresgid (gid, gid, gid)) < 0)
124 mu_error (_("setresgid(%lu,%lu,%lu) failed: %s"),
125 (unsigned long) gid,
126 (unsigned long) gid, (unsigned long) gid, mu_strerror (errno));
127#endif
128
129 if (rc == 0 && gid != 0)
130 {
131 if ((rc = setgid (gid)) < 0 && getegid () != gid)
132 mu_error (_("setgid(%lu) failed: %s"),
133 (unsigned long) gid, mu_strerror (errno));
134 if (rc == 0 && getegid () != gid)
135 {
136 mu_error (_("Cannot set effective gid to %lu"),
137 (unsigned long) gid);
138 rc = 1;
139 }
140 }
141
142 /* Now reset uid */
143 if (rc == 0 && uid != 0)
144 {
145 uid_t euid;
146
147 if (setuid (uid)
148 || geteuid () != uid
149 || (getuid () != uid && (geteuid () == 0 || getuid () == 0)))
150 {
151
152#if defined(HAVE_SETREUID)
153 if (geteuid () != uid)
154 {
155 if (setreuid (uid, -1) < 0)
156 {
157 mu_error (_("setreuid(%lu,-1) failed: %s"),
158 (unsigned long) uid, mu_strerror (errno));
159 rc = 1;
160 }
161 if (setuid (uid) < 0)
162 {
163 mu_error (_("second setuid(%lu) failed: %s"),
164 (unsigned long) uid, mu_strerror (errno));
165 rc = 1;
166 }
167 }
168 else
169#endif
170 {
171 mu_error (_("setuid(%lu) failed: %s"),
172 (unsigned long) uid, mu_strerror (errno));
173 rc = 1;
174 }
175 }
176
177 euid = geteuid ();
178 if (uid != 0 && setuid (0) == 0)
179 {
180 mu_error (_("seteuid(0) succeeded when it should not"));
181 rc = 1;
182 }
183 else if (uid != euid && setuid (euid) == 0)
184 {
185 mu_error (_("Cannot drop non-root setuid privileges"));
186 rc = 1;
187 }
188
189 }
190
191 return rc;
192}
193
194
195static int
196translate_item (void *item, void *data)
197{
198 mu_list_t dst = data;
199 struct group *group = getgrnam (item);
200 if (!group)
201 {
202 mu_error (_("Unknown group: %s"), (char *) item);
203 return 1;
204 }
205 return mu_list_append (dst, (void *) group->gr_gid);
206}
207
208static int
209grouplist_translate (mu_list_t * pdst, mu_list_t src)
210{
211 mu_list_t dst;
212 int rc;
213
214 if (!src)
215 return 0;
216 rc = mu_list_create (&dst);
217 if (rc)
218 {
219 mu_error (_("%s: cannot create list: %s"),
220 "grouplist_translate", mu_strerror (rc));
221 return rc;
222 }
223 *pdst = dst;
224 return mu_list_do (src, translate_item, dst);
225}
226
227void
228mf_priv_setup (struct mf_privs *privs)
229{
230 struct passwd *pw;
231 mu_list_t grp = NULL;
232
233 if (!privs || !privs->user)
234 return;
235
236 pw = getpwnam (privs->user);
237 if (!pw)
238 {
239 mu_error (_("No such user: %s"), privs->user);
240 exit (EX_CONFIG);
241 }
242
243 grouplist_translate (&grp, privs->groups);
244 if (privs->allgroups && get_user_groups (&grp, privs->user))
245 exit (EX_CONFIG);
246 if (switch_to_privs (pw->pw_uid, pw->pw_gid, grp))
247 exit (EX_SOFTWARE);
248 mu_list_destroy (&grp);
249}
250
251
252void
253mf_epriv_setup (struct mf_privs *privs) <