1 |
diff -ruN mailman-2.1.12-a/configure.in mailman-2.1.12-b/configure.in |
2 |
--- mailman-2.1.12-a/configure.in 2009-02-23 22:23:35.000000000 +0100 |
3 |
+++ mailman-2.1.12-b/configure.in 2009-07-28 12:19:47.000000000 +0200 |
4 |
@@ -249,26 +249,101 @@ |
5 |
fi |
6 |
|
7 |
# new macro for finding group names |
8 |
-AC_DEFUN([MM_FIND_GROUP_NAME], [ |
9 |
+# returns a comma separated list of quoted group names |
10 |
+# the list is returned in the same order as specified with any duplicates removed |
11 |
+# the filter flag must be "yes" or "no", e.g. this is permcheck |
12 |
+# "no" ==> none existing groups are not filtered out |
13 |
+# "yes" ==> only those groups that are in the group database are included |
14 |
+# in the list |
15 |
+AC_DEFUN(MM_FIND_GROUP_LIST, [ |
16 |
# $1 == variable name |
17 |
-# $2 == user id to check for |
18 |
+# $2 == white space separated list of groups to check, |
19 |
+# list may contain mix of id's and names |
20 |
+# $3 == filter, if == 'yes' then remove any non-existing groups |
21 |
AC_SUBST($1) |
22 |
changequote(,) |
23 |
if test -z "$$1" |
24 |
then |
25 |
cat > conftest.py <<EOF |
26 |
import grp |
27 |
-gid = '' |
28 |
+group_names = [] |
29 |
+seen = {} |
30 |
+filter = "$3" |
31 |
+ |
32 |
for group in "$2".split(): |
33 |
try: |
34 |
+ gid = int(group) |
35 |
+ try: |
36 |
+ gname = grp.getgrgid(gid)[0] |
37 |
+ except KeyError: |
38 |
+ gname = '' |
39 |
+ except ValueError: |
40 |
try: |
41 |
- gname = grp.getgrgid(int(group))[0] |
42 |
- break |
43 |
- except ValueError: |
44 |
gname = grp.getgrnam(group)[0] |
45 |
+ except KeyError: |
46 |
+ if filter == "yes": |
47 |
+ gname = '' |
48 |
+ else: |
49 |
+ gname = group |
50 |
+ if gname: |
51 |
+ if gname not in seen: |
52 |
+ seen[gname] = 1 |
53 |
+ group_names.append(gname) |
54 |
+ |
55 |
+if group_names: |
56 |
+ val = '"' + '", "'.join(group_names) + '"' |
57 |
+ #val = "'"+val+"'" |
58 |
+else: |
59 |
+ val = '' |
60 |
+ |
61 |
+fp = open("conftest.out", "w") |
62 |
+fp.write("%s\n" % val) |
63 |
+fp.close() |
64 |
+EOF |
65 |
+ $PYTHON conftest.py |
66 |
+ $1=`cat conftest.out` |
67 |
+fi |
68 |
+changequote([, ]) |
69 |
+rm -f conftest.out conftest.py]) |
70 |
+ |
71 |
+ |
72 |
+# new macro for finding group names |
73 |
+AC_DEFUN(MM_FIND_GROUP_NAME, [ |
74 |
+# Given a list of tokens, either a name or a number (gid) |
75 |
+# return the first one in the list that is found in the |
76 |
+# group database. The return value is always a name, possibly |
77 |
+# translated from a gid. If permcheck is "no" then the group |
78 |
+# database is not checked, instead the first token in the list |
79 |
+# which is a name is returned (e.g. the default value). If permcheck |
80 |
+# is no and only gid's are in the list then the null string is returned. |
81 |
+# $1 == variable name |
82 |
+# $2 == group id to check for |
83 |
+# $3 == permcheck, either "yes" or "no" |
84 |
+AC_SUBST($1) |
85 |
+changequote(,) |
86 |
+if test -z "$$1" |
87 |
+then |
88 |
+ cat > conftest.py <<EOF |
89 |
+import grp |
90 |
+gname='' |
91 |
+if "$3" == "yes": |
92 |
+ for group in "$2".split(): |
93 |
+ try: |
94 |
+ try: |
95 |
+ gname = grp.getgrgid(int(group))[0] |
96 |
+ break |
97 |
+ except ValueError: |
98 |
+ gname = grp.getgrnam(group)[0] |
99 |
+ break |
100 |
+ except KeyError: |
101 |
+ gname = '' |
102 |
+else: |
103 |
+ for group in "$2".split(): |
104 |
+ try: |
105 |
+ int(group) |
106 |
+ except ValueError: |
107 |
+ gname = group |
108 |
break |
109 |
- except KeyError: |
110 |
- gname = '' |
111 |
fp = open("conftest.out", "w") |
112 |
fp.write("%s\n" % gname) |
113 |
fp.close() |
114 |
@@ -282,25 +357,41 @@ |
115 |
|
116 |
# new macro for finding UIDs |
117 |
AC_DEFUN([MM_FIND_USER_NAME], [ |
118 |
+# Given a list of tokens, either a name or a number (uid) |
119 |
+# return the first one in the list that is found in the |
120 |
+# password database. The return value is always a name, possibly |
121 |
+# translated from a uid. If permcheck is "no" then the password |
122 |
+# database is not checked, instead the first token in the list |
123 |
+# which is a name is returned (e.g. the default value). If permcheck |
124 |
+# is no and only uid's are in the list then the null string is returned. |
125 |
# $1 == variable name |
126 |
# $2 == user id to check for |
127 |
+# $3 == permcheck, either "yes" or "no" |
128 |
AC_SUBST($1) |
129 |
changequote(,) |
130 |
if test -z "$$1" |
131 |
then |
132 |
cat > conftest.py <<EOF |
133 |
import pwd |
134 |
-uid = '' |
135 |
-for user in "$2".split(): |
136 |
- try: |
137 |
+uname='' |
138 |
+if "$3" == "yes": |
139 |
+ for user in "$2".split(): |
140 |
try: |
141 |
- uname = pwd.getpwuid(int(user))[0] |
142 |
- break |
143 |
+ try: |
144 |
+ uname = pwd.getpwuid(int(user))[0] |
145 |
+ break |
146 |
+ except ValueError: |
147 |
+ uname = pwd.getpwnam(user)[0] |
148 |
+ break |
149 |
+ except KeyError: |
150 |
+ uname = '' |
151 |
+else: |
152 |
+ for user in "$2".split(): |
153 |
+ try: |
154 |
+ int(user) |
155 |
except ValueError: |
156 |
- uname = pwd.getpwnam(user)[0] |
157 |
+ uname = user |
158 |
break |
159 |
- except KeyError: |
160 |
- uname = '' |
161 |
fp = open("conftest.out", "w") |
162 |
fp.write("%s\n" % uname) |
163 |
fp.close() |
164 |
@@ -326,7 +417,7 @@ |
165 |
# User `mailman' must exist |
166 |
AC_SUBST(MAILMAN_USER) |
167 |
AC_MSG_CHECKING(for user name \"$USERNAME\") |
168 |
-MM_FIND_USER_NAME(MAILMAN_USER, $USERNAME) |
169 |
+MM_FIND_USER_NAME(MAILMAN_USER, $USERNAME, $with_permcheck) |
170 |
if test -z "$MAILMAN_USER" |
171 |
then |
172 |
if test "$with_permcheck" = "yes" |
173 |
@@ -357,7 +448,7 @@ |
174 |
# Target group must exist |
175 |
AC_SUBST(MAILMAN_GROUP) |
176 |
AC_MSG_CHECKING(for group name \"$GROUPNAME\") |
177 |
-MM_FIND_GROUP_NAME(MAILMAN_GROUP, $GROUPNAME) |
178 |
+MM_FIND_GROUP_NAME(MAILMAN_GROUP, $GROUPNAME, $with_permcheck) |
179 |
if test -z "$MAILMAN_GROUP" |
180 |
then |
181 |
if test "$with_permcheck" = "yes" |
182 |
@@ -380,11 +471,11 @@ |
183 |
prefix = "$prefixcheck" |
184 |
groupname = "$GROUPNAME" |
185 |
mailmangroup = "$MAILMAN_GROUP" |
186 |
-try: |
187 |
- mailmangid = grp.getgrnam(mailmangroup)[2] |
188 |
-except KeyError: |
189 |
- mailmangid = -1 |
190 |
problems = [] |
191 |
+try: mailmangid = grp.getgrnam(mailmangroup)[2] |
192 |
+except KeyError: |
193 |
+ problems.append("group doesn't exist: " + mailmangroup) |
194 |
+ mailmangid = 41 |
195 |
try: statdata = os.stat(prefix) |
196 |
except OSError: |
197 |
problems.append("Directory doesn't exist: " + prefix) |
198 |
@@ -434,7 +525,7 @@ |
199 |
then |
200 |
with_mail_gid="mailman other mail daemon" |
201 |
fi |
202 |
-MM_FIND_GROUP_NAME(MAIL_GROUP, $with_mail_gid) |
203 |
+MM_FIND_GROUP_LIST(MAIL_GROUP, $with_mail_gid, $with_permcheck) |
204 |
if test -z "$MAIL_GROUP" |
205 |
then |
206 |
if test "$with_permcheck" = "yes" |
207 |
@@ -461,7 +552,7 @@ |
208 |
with_cgi_gid="www www-data nobody" |
209 |
fi |
210 |
|
211 |
-MM_FIND_GROUP_NAME(CGI_GROUP, $with_cgi_gid) |
212 |
+MM_FIND_GROUP_LIST(CGI_GROUP, $with_cgi_gid, $with_permcheck) |
213 |
if test -z "$CGI_GROUP" |
214 |
then |
215 |
if test "$with_permcheck" = "yes" |
216 |
diff -ruN mailman-2.1.12-a/src/cgi-wrapper.c mailman-2.1.12-b/src/cgi-wrapper.c |
217 |
--- mailman-2.1.12-a/src/cgi-wrapper.c 2009-02-23 22:23:35.000000000 +0100 |
218 |
+++ mailman-2.1.12-b/src/cgi-wrapper.c 2009-07-28 12:19:47.000000000 +0200 |
219 |
@@ -28,11 +28,11 @@ |
220 |
/* Group name that CGI scripts run as. See your web server's documentation |
221 |
* for details. |
222 |
*/ |
223 |
-#define LEGAL_PARENT_GROUP CGI_GROUP |
224 |
+#define LEGAL_PARENT_GROUPS CGI_GROUP |
225 |
|
226 |
const char* logident = LOG_IDENT; |
227 |
char* script = SCRIPTNAME; |
228 |
-const char* parentgroup = LEGAL_PARENT_GROUP; |
229 |
+const char* parentgroups[] = {LEGAL_PARENT_GROUPS}; |
230 |
|
231 |
|
232 |
int |
233 |
@@ -42,7 +42,7 @@ |
234 |
char* fake_argv[3]; |
235 |
|
236 |
running_as_cgi = 1; |
237 |
- check_caller(logident, parentgroup); |
238 |
+ check_caller(logident, parentgroups, sizeof(parentgroups) / sizeof(parentgroups[0])); |
239 |
|
240 |
/* For these CGI programs, we can ignore argc and argv since they |
241 |
* don't contain anything useful. `script' will always be the driver |
242 |
diff -ruN mailman-2.1.12-a/src/common.c mailman-2.1.12-b/src/common.c |
243 |
--- mailman-2.1.12-a/src/common.c 2009-02-23 22:23:35.000000000 +0100 |
244 |
+++ mailman-2.1.12-b/src/common.c 2009-07-28 12:19:47.000000000 +0200 |
245 |
@@ -117,13 +117,14 @@ |
246 |
/* Is the parent process allowed to call us? |
247 |
*/ |
248 |
void |
249 |
-check_caller(const char* ident, const char* parentgroup) |
250 |
+check_caller(const char* ident, const char** parentgroups, size_t numgroups) |
251 |
{ |
252 |
GID_T mygid = getgid(); |
253 |
struct group *mygroup = getgrgid(mygid); |
254 |
char* option; |
255 |
char* server; |
256 |
char* wrapper; |
257 |
+ int i; |
258 |
|
259 |
if (running_as_cgi) { |
260 |
option = "--with-cgi-gid"; |
261 |
@@ -136,28 +137,46 @@ |
262 |
wrapper = "mail"; |
263 |
} |
264 |
|
265 |
- if (!mygroup) |
266 |
- fatal(ident, GROUP_NAME_NOT_FOUND, |
267 |
- "Failure to find group name for GID %d. Mailman\n" |
268 |
- "expected the %s wrapper to be executed as group\n" |
269 |
- "\"%s\", but the system's %s server executed the\n" |
270 |
- "wrapper as GID %d for which the name could not be\n" |
271 |
- "found. Try adding GID %d to your system as \"%s\",\n" |
272 |
- "or tweak your %s server to run the wrapper as group\n" |
273 |
- "\"%s\".", |
274 |
- mygid, wrapper, parentgroup, server, mygid, mygid, |
275 |
- parentgroup, server, parentgroup); |
276 |
+ if (!mygroup) |
277 |
+ fatal(ident, GROUP_ID_NOT_FOUND, |
278 |
+ "Failure to lookup via getgrgid() the group info for group id %d that this Mailman %s wrapper is executing under.\n" |
279 |
+ "This is probably due to an incorrectly configured system and is not a Mailman problem", |
280 |
+ mygid, wrapper); |
281 |
+ |
282 |
+ for (i = 0; i < numgroups; i++) { |
283 |
+ if (strcmp(parentgroups[i], mygroup->gr_name) == 0) break; |
284 |
+ } |
285 |
+ |
286 |
+ if (i >= numgroups) { |
287 |
+ char *groupset = NULL; |
288 |
+ size_t size = 0; |
289 |
+ |
290 |
+ for (i = 0; i < numgroups; i++) { |
291 |
+ size += strlen(parentgroups[i]) + 2; |
292 |
+ } |
293 |
+ |
294 |
+ groupset = malloc(size); |
295 |
+ |
296 |
+ if (groupset) { |
297 |
+ groupset[0] = 0; |
298 |
+ for (i = 0; i < numgroups; i++) { |
299 |
+ strcat(groupset, parentgroups[i]); |
300 |
+ if (i < numgroups-1) strcat(groupset, ", "); |
301 |
+ } |
302 |
+ } |
303 |
|
304 |
- if (strcmp(parentgroup, mygroup->gr_name)) |
305 |
fatal(ident, GROUP_MISMATCH, |
306 |
- "Group mismatch error. Mailman expected the %s\n" |
307 |
- "wrapper script to be executed as group \"%s\", but\n" |
308 |
- "the system's %s server executed the %s script as\n" |
309 |
- "group \"%s\". Try tweaking the %s server to run the\n" |
310 |
- "script as group \"%s\", or re-run configure, \n" |
311 |
- "providing the command line option `%s=%s'.", |
312 |
- wrapper, parentgroup, server, wrapper, mygroup->gr_name, |
313 |
- server, parentgroup, option, mygroup->gr_name); |
314 |
+ "Group mismatch error. Mailman expected the %s wrapper script to be\n" |
315 |
+ "executed as one of the following groups:\n" |
316 |
+ "[%s],\n" |
317 |
+ "but the system's %s server executed the %s script as group: \"%s\".\n" |
318 |
+ "Try tweaking the %s server to run the script as one of these groups:\n" |
319 |
+ "[%s],\n" |
320 |
+ "or re-run configure providing the command line option:\n" |
321 |
+ "'%s=%s'.", |
322 |
+ wrapper, groupset, server, wrapper, mygroup->gr_name, |
323 |
+ server, groupset, option, mygroup->gr_name); |
324 |
+ } |
325 |
} |
326 |
|
327 |
|
328 |
diff -ruN mailman-2.1.12-a/src/common.h mailman-2.1.12-b/src/common.h |
329 |
--- mailman-2.1.12-a/src/common.h 2009-02-23 22:23:35.000000000 +0100 |
330 |
+++ mailman-2.1.12-b/src/common.h 2009-07-28 12:19:47.000000000 +0200 |
331 |
@@ -33,7 +33,7 @@ |
332 |
#define GID_T GETGROUPS_T |
333 |
|
334 |
extern void fatal(const char*, int, char*, ...); |
335 |
-extern void check_caller(const char*, const char*); |
336 |
+extern void check_caller(const char* ident, const char**, size_t); |
337 |
extern int run_script(const char*, int, char**, char**); |
338 |
|
339 |
/* Global variable used as a flag. */ |
340 |
@@ -51,7 +51,7 @@ |
341 |
#define MAIL_USAGE_ERROR 5 |
342 |
#define MAIL_ILLEGAL_COMMAND 6 |
343 |
#define ADDALIAS_USAGE_ERROR 7 |
344 |
-#define GROUP_NAME_NOT_FOUND 8 |
345 |
+#define GROUP_ID_NOT_FOUND 8 |
346 |
|
347 |
|
348 |
/* |
349 |
diff -ruN mailman-2.1.12-a/src/mail-wrapper.c mailman-2.1.12-b/src/mail-wrapper.c |
350 |
--- mailman-2.1.12-a/src/mail-wrapper.c 2009-02-23 22:23:35.000000000 +0100 |
351 |
+++ mailman-2.1.12-b/src/mail-wrapper.c 2009-07-28 12:19:47.000000000 +0200 |
352 |
@@ -23,9 +23,9 @@ |
353 |
/* Group name that your mail programs run as. See your mail server's |
354 |
* documentation for details. |
355 |
*/ |
356 |
-#define LEGAL_PARENT_GROUP MAIL_GROUP |
357 |
+#define LEGAL_PARENT_GROUPS MAIL_GROUP |
358 |
|
359 |
-const char* parentgroup = LEGAL_PARENT_GROUP; |
360 |
+const char* parentgroups[] = {LEGAL_PARENT_GROUPS}; |
361 |
const char* logident = "Mailman mail-wrapper"; |
362 |
|
363 |
|
364 |
@@ -74,7 +74,7 @@ |
365 |
fatal(logident, MAIL_ILLEGAL_COMMAND, |
366 |
"Illegal command: %s", argv[1]); |
367 |
|
368 |
- check_caller(logident, parentgroup); |
369 |
+ check_caller(logident, parentgroups, sizeof(parentgroups) / sizeof(parentgroups[0])); |
370 |
|
371 |
/* If we got here, everything must be OK */ |
372 |
status = run_script(argv[1], argc, argv, env); |
373 |
diff -ruN mailman-2.1.12-a/src/Makefile.in mailman-2.1.12-b/src/Makefile.in |
374 |
--- mailman-2.1.12-a/src/Makefile.in 2009-02-23 22:23:35.000000000 +0100 |
375 |
+++ mailman-2.1.12-b/src/Makefile.in 2009-07-28 12:19:47.000000000 +0200 |
376 |
@@ -49,9 +49,9 @@ |
377 |
|
378 |
SHELL= /bin/sh |
379 |
|
380 |
-MAIL_FLAGS= -DMAIL_GROUP="\"$(MAIL_GROUP)\"" |
381 |
+MAIL_FLAGS= -DMAIL_GROUP='$(MAIL_GROUP)' |
382 |
|
383 |
-CGI_FLAGS= -DCGI_GROUP="\"$(CGI_GROUP)\"" |
384 |
+CGI_FLAGS= -DCGI_GROUP='$(CGI_GROUP)' |
385 |
|
386 |
HELPFUL= -DHELPFUL |
387 |
|