hmm. yes, that might be sensible of me :} i haven't touched 1.x in so
long, i have no idea if it's applicable. my understanding from Timo is
that it's been this way for quite some time so it would likely be easy
to massage into place.
it's linked at
http://stuph.org/dovecot-2.0.5-bad-permissions-inheritance.patch and
attached.
-d
On 11/10/2010 01:54 PM, Marcus Rueckert wrote:
> On 2010-11-10 13:48:13 -0500, David Ford wrote:
>> Use this patch, it fixes dovecot's ownership inheritance assumptions.
> [snip]
>
> 1. he is using 1.2.9 and your patch is for 2.0, would your patch work
> for 1.2.9 aswell.
>
> 2. you want to attach the patch and not paste it inline.
> your mail client mangled the lines.
>
> darix
>
--- src/lib-storage/mailbox-list.c.orig 2010-09-14 11:03:18.000000000 -0400
+++ src/lib-storage/mailbox-list.c 2010-10-14 15:20:15.000000000 -0400
@@ -25,6 +25,9 @@
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
+#include <stdlib.h>
+#include <grp.h>
+#include <pwd.h>
/* 20 * (200+1) < 4096 which is the standard PATH_MAX. Having these settings
prevents malicious user from creating eg. "a/a/a/.../a" mailbox name and
@@ -450,7 +453,7 @@
}
if (S_ISDIR(st.st_mode) && (st.st_mode & S_ISGID) != 0) {
- /* directory's GID is used automatically for new
+ /* directory is sgid, so GID is used automatically for
new
files */
*gid_r = (gid_t)-1;
} else if ((st.st_mode & 0070) >> 3 == (st.st_mode & 0007)) {
@@ -460,8 +463,39 @@
} else if (getegid() == st.st_gid) {
/* using our own gid, no need to change it */
*gid_r = (gid_t)-1;
- } else {
- *gid_r = st.st_gid;
+ }
+
+ else {
+ /* test for unusable inheritance. logic sets fgid_me to
st.gid
+ for unlikely case of lookup failure and we just fall
through */
+ int j, ngroups = 999;
+ gid_t *groups;
+ gid_t fgid_me = st.st_gid;
+
+ groups = malloc(ngroups * sizeof (gid_t));
+ if (groups != NULL) {
+ uid_t egid = getegid();
+ struct passwd *pw = getpwuid(geteuid());
+ if (pw != NULL) {
+ /* get pw entry for test using my
current effective uid */
+ if (getgrouplist(pw->pw_name, egid,
groups, &ngroups) != -1) {
+ /* get list of group IDs my
euid belongs to, ngroups
+ will be set to the number of
groups I belong to */
+ fgid_me = egid;
+ for (j = 0; j < ngroups; j++) {
+ /* enumerate list, test
to see if i belong
+ to gid of parent
directory */
+ if (st.st_gid ==
groups[j]) {
+ /* if so,
switch to parent gid */
+ fgid_me =
st.st_gid;
+ }
+ }
+ }
+ }
+ free(groups);
+ }
+
+ *gid_r = fgid_me;
}
}