COMMAND
sendmail
SYSTEMS AFFECTED
Systems running sendmail 8.8.4
PROBLEM
The initgroups() is not done until deliver.c??? The *purpose*
behind the setuid/setgid/initgroups is for security right? So in
main, you have:
if (OpMode != MD_DAEMON && OpMode != MD_FGDAEMON)
{
/* drop privileges -- daemon mode done after socket/bind */
if (RunAsGid != 0)
(void) setgid(RunAsGid);
if (RunAsUid != 0)
(void) setuid(RunAsUid);
}
and:
/* drop privileges */
if (RunAsGid != 0)
(void) setgid(RunAsGid);
if (RunAsUid != 0)
(void) setuid(RunAsUid);
So we set the uid and gid here; but we are *STILL* not calling
initgroups here as we should. There is no reason to keep all of
those groups when we are explicitly saying "use this uid:gid"...
SOLUTION
------- main.c -------
*** - Wed Dec 31 16:00:00 1969
--- main.c Fri Dec 6 11:01:10 1996
***************
*** 139,144 ****
--- 139,145 ----
extern void printqueue __P((void));
extern void sendtoargv __P((char **, ENVELOPE *));
extern void resetlimits __P((void));
+ extern void drop_privileges __P((void));
/*
** Check to see if we reentered.
***************
*** 202,207 ****
--- 203,211 ----
tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
+ /* drop group id privileges (RunAsUser not yet set) */
+ drop_privileges();
+
/* Handle any non-getoptable constructions. */
obsolete(argv);
***************
*** 780,789 ****
if (OpMode != MD_DAEMON && OpMode != MD_FGDAEMON)
{
/* drop privileges -- daemon mode done after socket/bind */
! if (RunAsGid != 0)
! (void) setgid(RunAsGid);
! if (RunAsUid != 0)
! (void) setuid(RunAsUid);
}
/*
--- 784,790 ----
if (OpMode != MD_DAEMON && OpMode != MD_FGDAEMON)
{
/* drop privileges -- daemon mode done after socket/bind */
! drop_privileges();
}
/*
***************
*** 1292,1301 ****
nullserver = getrequests(CurEnv);
/* drop privileges */
! if (RunAsGid != 0)
! (void) setgid(RunAsGid);
! if (RunAsUid != 0)
! (void) setuid(RunAsUid);
/* at this point we are in a child: reset state */
(void) newenvelope(CurEnv, CurEnv);
--- 1293,1299 ----
nullserver = getrequests(CurEnv);
/* drop privileges */
! drop_privileges();
/* at this point we are in a child: reset state */
(void) newenvelope(CurEnv, CurEnv);
***************
*** 1956,1961 ****
--- 1954,1984 ----
syslog(LOG_ALERT, "could not exec %s: %m", SaveArgv[0]);
#endif
exit(EX_OSFILE);
+ }
+ /*
+ ** DROP_PRIVILEGES -- reduce privileges to those of the RunAsUser option
+ **
+ ** Parameters:
+ ** none.
+ **
+ ** Returns:
+ ** none.
+ */
+
+ void
+ drop_privileges()
+ {
+ #ifdef NGROUPS_MAX
+ /* reset group permissions; these can be set later */
+ GIDSET_T emptygidset[NGROUPS_MAX];
+
+ emptygidset[0] = RunAsGid == 0 ? geteuid() : RunAsGid;
+ (void) setgroups(1, emptygidset);
+ #endif
+ if (RunAsGid != 0)
+ (void) setgid(RunAsGid);
+ if (RunAsUid != 0)
+ (void) setuid(RunAsUid);
}
/*
** TESTMODELINE -- process a test mode input line
------- queue.c -------
*** - Wed Dec 31 16:00:00 1969
--- queue.c Fri Dec 6 11:01:16 1996
***************
*** 527,532 ****
--- 527,533 ----
extern ENVELOPE BlankEnvelope;
extern void clrdaemon __P((void));
extern void runqueueevent __P((bool));
+ extern void drop_privileges __P((void));
/*
** If no work will ever be selected, don't even bother reading
***************
*** 631,642 ****
/* drop privileges */
if (geteuid() == (uid_t) 0)
! {
! if (RunAsGid != (gid_t) 0)
! (void) setgid(RunAsGid);
! if (RunAsUid != (uid_t) 0)
! (void) setuid(RunAsUid);
! }
/*
** Create ourselves an envelope
--- 632,638 ----
/* drop privileges */
if (geteuid() == (uid_t) 0)
! drop_privileges();
/*
** Create ourselves an envelope