/[smecontribs]/rpms/mailman/contribs7/mailman-2.1-multimail.patch
ViewVC logotype

Annotation of /rpms/mailman/contribs7/mailman-2.1-multimail.patch

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.3 - (hide annotations) (download)
Tue Nov 25 16:20:13 2008 UTC (15 years, 11 months ago) by slords
Branch: MAIN
CVS Tags: HEAD
Changes since 1.2: +0 -0 lines
Restore

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

admin@koozali.org
ViewVC Help
Powered by ViewVC 1.2.1 RSS 2.0 feed