diff options
Diffstat (limited to 'lib/userprivs.c')
-rw-r--r-- | lib/userprivs.c | 291 |
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 | |||
36 | int | ||
37 | get_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 */ | ||
74 | int | ||
75 | switch_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 | |||
195 | static int | ||
196 | translate_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 | |||
208 | static int | ||
209 | grouplist_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 | |||
227 | void | ||
228 | mf_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 | |||
252 | void | ||
253 | mf_epriv_setup (struct mf_privs *privs) | < |