diff options
| -rw-r--r-- | lib-src/ChangeLog | 6 | ||||
| -rw-r--r-- | lib-src/movemail.c | 45 | 
2 files changed, 25 insertions, 26 deletions
| diff --git a/lib-src/ChangeLog b/lib-src/ChangeLog index ad7ce6da3c2..11e603eab0f 100644 --- a/lib-src/ChangeLog +++ b/lib-src/ChangeLog @@ -1,3 +1,9 @@ +2010-04-02  Dan Rosenberg  <dan.j.rosenberg@gmail.com>  (tiny change) + +	* movemail.c (main): Check return values of setuid.  Avoid +	possibility of symlink attack when movemail is setgid mail +	(CVE-2010-0825). +  2010-04-02  Dan Nicolaescu  <dann@ics.uci.edu>  	Remove extern errno declarations. diff --git a/lib-src/movemail.c b/lib-src/movemail.c index a887eb216ac..ea307241351 100644 --- a/lib-src/movemail.c +++ b/lib-src/movemail.c @@ -194,6 +194,9 @@ main (argc, argv)  # define ARGSTR "p"  #endif /* MAIL_USE_POP */ +  uid_t real_gid = getgid(); +  uid_t priv_gid = getegid(); +  #ifdef WINDOWSNT    /* Ensure all file i/o is in binary mode. */    _fmode = _O_BINARY; @@ -244,25 +247,6 @@ main (argc, argv)    if (*outname == 0)      fatal ("Destination file name is empty", 0, 0); -  /* Check access to output file.  */ -  if (access (outname, F_OK) == 0 && access (outname, W_OK) != 0) -    pfatal_with_name (outname); - -  /* Also check that outname's directory is writable to the real uid.  */ -  { -    char *buf = (char *) xmalloc (strlen (outname) + 1); -    char *p; -    strcpy (buf, outname); -    p = buf + strlen (buf); -    while (p > buf && !IS_DIRECTORY_SEP (p[-1])) -      *--p = 0; -    if (p == buf) -      *p++ = '.'; -    if (access (buf, W_OK) != 0) -      pfatal_with_name (buf); -    free (buf); -  } -  #ifdef MAIL_USE_POP    if (!strncmp (inname, "po:", 3))      { @@ -274,15 +258,12 @@ main (argc, argv)        exit (status);      } -  setuid (getuid ()); +  if (setuid (getuid ()) < 0) +    fatal ("Failed to drop privileges", 0, 0); +  #endif /* MAIL_USE_POP */  #ifndef DISABLE_DIRECT_ACCESS - -  /* Check access to input file.  */ -  if (access (inname, R_OK | W_OK) != 0) -    pfatal_with_name (inname); -  #ifndef MAIL_USE_MMDF  #ifndef MAIL_USE_SYSTEM_LOCK  #ifdef MAIL_USE_MAILLOCK @@ -376,7 +357,8 @@ main (argc, argv)        time_t touched_lock, now;  #endif -      setuid (getuid ()); +      if (setuid (getuid ()) < 0 || setegid (real_gid) < 0) +	fatal ("Failed to drop privileges", 0, 0);  #ifndef MAIL_USE_MMDF  #ifdef MAIL_USE_SYSTEM_LOCK @@ -402,6 +384,9 @@ main (argc, argv)        if (outdesc < 0)  	pfatal_with_name (outname); +      if (setegid (priv_gid) < 0) +	fatal ("Failed to regain privileges", 0, 0); +        /* This label exists so we can retry locking  	 after a delay, if it got EAGAIN or EBUSY.  */      retry_lock: @@ -495,6 +480,10 @@ main (argc, argv)  	pfatal_and_delete (outname);  #endif +      /* Prevent symlink attacks truncating other users' mailboxes */ +      if (setegid (real_gid) < 0) +	fatal ("Failed to drop privileges", 0, 0); +        /* Check to make sure no errors before we zap the inbox.  */        if (close (outdesc) != 0)  	pfatal_and_delete (outname); @@ -526,6 +515,10 @@ main (argc, argv)  	}  #endif /* not MAIL_USE_SYSTEM_LOCK */ +      /* End of mailbox truncation */ +      if (setegid (priv_gid) < 0) +	fatal ("Failed to regain privileges", 0, 0); +  #ifdef MAIL_USE_MAILLOCK        /* This has to occur in the child, i.e., in the process that           acquired the lock! */ | 
