commit b31382fa8c60e0ddaa0b406b0f172f5edcce3aa3 Author: Shaddy Baddah Commit: Shaddy Baddah Previously, only SYSTEM user is prevented from preauthentication, by emulating root if the uid matches the RID of the regular SYSTEM user. Every other owner of the imapd process is considered non-root and therefore, preauthenticated. From Windows 2003 Server (I think), Cygwin has had to create an alternative SYSTEM user, with CreateToken privilege. Usually, it is called cyg_server, and the csih helper scripts (ssh-host-config, iu-config, etc.) use this as the default user to start the Windows service under. This meant that on those systems, imapd would consider this non-SYSTEM user as preauthenticated. This would mean that any imapd connection would not be authenticated and automatically pointed at /var/empty as the home directory containing imap folders. This patch resolves this in an not so direct way. The intention of the original imap code is to disallow root/privileged users from being preauthenticated. So this patch also (to SYSTEM user) disallows preauth (by emulating root) if the process owner (cyg_server) is in the Administrators group. Again, it checks against the RID of the regular Administrators group, although this can also be circumvented with /etc/group mods. Small price to pay for simplicity. diff --git a/src/osdep/unix/os_cyg.c b/src/osdep/unix/os_cyg.c old mode 100644 new mode 100755 index c9cd2f7..5ca7e5b --- a/src/osdep/unix/os_cyg.c +++ b/src/osdep/unix/os_cyg.c @@ -41,6 +41,7 @@ extern int errno; /* just in case */ #include #include +#include #include "misc.h" @@ -57,6 +58,10 @@ extern int errno; /* just in case */ #include "flockcyg.c" #include "gethstid.c" +/* compromise (for sake of a reasonable stack frame and avoiding calling + malloc. if we can't find the Administrators gid within the bounds, be + prudent and return 0 uid */ +#define GIDS_FOR_SEARCH_SIZE 12 /* Emulator for geteuid() call * Returns: effective UID @@ -66,6 +71,19 @@ extern int errno; /* just in case */ uid_t Geteuid (void) { + gid_t my_gids[GIDS_FOR_SEARCH_SIZE]; + int num_gids, idx; uid_t ret = geteuid (); - return (ret == SYSTEMUID) ? 0 : ret; + if (ret == SYSTEMUID) + return 0; + + /* find if the groups the process owner is in includes Administrators */ + num_gids = getgroups(GIDS_FOR_SEARCH_SIZE, my_gids); + for (idx = 0; + (idx < num_gids) && (my_gids[idx] != ADMINISTRATORSGID); + idx++); + + /* if we are in Administrators (idx within my_gids) then return root uid, + else the user can be considered preauth'ed */ + return (idx < num_gids) ? 0 : ret; } diff --git a/src/osdep/unix/os_cyg.h b/src/osdep/unix/os_cyg.h old mode 100644 new mode 100755 index 061db33..836f551 --- a/src/osdep/unix/os_cyg.h +++ b/src/osdep/unix/os_cyg.h @@ -47,6 +47,8 @@ #define setpgrp setpgid #define SYSTEMUID 18 /* Cygwin returns this for SYSTEM */ +#define ADMINISTRATORSGID 544 /* Cygwin returns this for Administrators */ + #define geteuid Geteuid uid_t Geteuid (void);