X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/f5d0ac07d63bfce83dcf45045b4541fe7a1bca7c..8838172bf0c35831f6b0f0a9763af0d04edf5468:/lib-src/movemail.c diff --git a/lib-src/movemail.c b/lib-src/movemail.c index dd3b8291cc..ae51df3d39 100644 --- a/lib-src/movemail.c +++ b/lib-src/movemail.c @@ -1,7 +1,7 @@ /* movemail foo bar -- move file foo to file bar, locking file foo the way /bin/mail respects. Copyright (C) 1986, 1992, 1993, 1994, 1996, 1999, 2001, 2002, 2003, 2004, - 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -60,6 +60,7 @@ along with GNU Emacs. If not, see . */ #include #include #include +#include #include #ifdef HAVE_UNISTD_H @@ -196,6 +197,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; @@ -228,7 +232,7 @@ main (argc, argv) ) { #ifdef MAIL_USE_POP - fprintf (stderr, "Usage: movemail [-p] inbox destfile%s\n", + fprintf (stderr, "Usage: movemail [-p] [-r] inbox destfile%s\n", " [POP-password]"); #else fprintf (stderr, "Usage: movemail [-p] inbox destfile%s\n", ""); @@ -246,25 +250,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)) { @@ -276,15 +261,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 @@ -375,10 +357,11 @@ main (argc, argv) int lockcount = 0; int status = 0; #if defined (MAIL_USE_MAILLOCK) && defined (HAVE_TOUCHLOCK) - long touched_lock, now; + 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 @@ -404,6 +387,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: @@ -497,6 +483,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); @@ -528,6 +518,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! */ @@ -683,6 +677,7 @@ xmalloc (size) #include #endif #include +#include #define NOTOK (-1) #define OK 0 @@ -923,7 +918,16 @@ int mbx_delimit_begin (mbf) FILE *mbf; { - if (fputs ("\f\n0, unseen,,\n", mbf) == EOF) + time_t now; + struct tm *ltime; + char fromline[40] = "From movemail "; + + now = time (NULL); + ltime = localtime (&now); + + strcat (fromline, asctime (ltime)); + + if (fputs (fromline, mbf) == EOF) return (NOTOK); return (OK); } @@ -932,7 +936,7 @@ int mbx_delimit_end (mbf) FILE *mbf; { - if (putc ('\037', mbf) == EOF) + if (putc ('\n', mbf) == EOF) return (NOTOK); return (OK); }