X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/6eabc4c2f76441f11cc344891d3849ad3631ab15..8838172bf0c35831f6b0f0a9763af0d04edf5468:/lib-src/movemail.c diff --git a/lib-src/movemail.c b/lib-src/movemail.c index 84d4f949b2..ae51df3d39 100644 --- a/lib-src/movemail.c +++ b/lib-src/movemail.c @@ -1,14 +1,14 @@ /* 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 Free Software Foundation, Inc. + 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GNU Emacs. -GNU Emacs is free software; you can redistribute it and/or modify +GNU Emacs is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -16,9 +16,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GNU Emacs; see the file COPYING. If not, write to -the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. */ +along with GNU Emacs. If not, see . */ + /* Important notice: defining MAIL_USE_FLOCK or MAIL_USE_LOCKF *will cause loss of mail* if you do it on a system that does not normally @@ -55,13 +54,13 @@ Boston, MA 02110-1301, USA. */ * */ -#define NO_SHORTNAMES /* Tell config not to load remap.h */ #include #include #include #include #include #include +#include #include #ifdef HAVE_UNISTD_H @@ -113,7 +112,7 @@ Boston, MA 02110-1301, USA. */ #define R_OK 4 #endif -#if defined (XENIX) || defined (WINDOWSNT) +#ifdef WINDOWSNT #include #endif @@ -175,7 +174,7 @@ main (argc, argv) char *inname, *outname; int indesc, outdesc; int nread; - WAITTYPE status; + int status; int c, preserve_mail = 0; #ifndef MAIL_USE_SYSTEM_LOCK @@ -198,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; @@ -230,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", ""); @@ -248,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)) { @@ -278,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 @@ -343,6 +323,13 @@ main (argc, argv) close (desc); tem = link (tempname, lockname); + +#ifdef EPERM + if (tem < 0 && errno == EPERM) + fatal ("Unable to create hard link between %s and %s", + tempname, lockname); +#endif + unlink (tempname); if (tem >= 0) break; @@ -370,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 @@ -388,17 +376,20 @@ main (argc, argv) if (indesc < 0) pfatal_with_name (inname); -#if defined (BSD_SYSTEM) || defined (XENIX) +#ifdef BSD_SYSTEM /* In case movemail is setuid to root, make sure the user can read the output file. */ /* This is desirable for all systems but I don't want to assume all have the umask system call */ umask (umask (0) & 0333); -#endif /* BSD_SYSTEM || XENIX */ +#endif /* BSD_SYSTEM */ outdesc = open (outname, O_WRONLY | O_CREAT | O_EXCL, 0666); 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: @@ -422,15 +413,11 @@ main (argc, argv) #ifdef MAIL_USE_LOCKF status = lockf (indesc, F_LOCK, 0); #else /* not MAIL_USE_LOCKF */ -#ifdef XENIX - status = locking (indesc, LK_RLCK, 0L); -#else #ifdef WINDOWSNT status = locking (indesc, LK_RLCK, -1L); #else status = flock (indesc, LOCK_EX); #endif -#endif #endif /* not MAIL_USE_LOCKF */ #endif /* MAIL_USE_SYSTEM_LOCK */ } @@ -496,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); @@ -503,13 +494,7 @@ main (argc, argv) #ifdef MAIL_USE_SYSTEM_LOCK if (! preserve_mail) { -#if defined (STRIDE) || defined (XENIX) - /* Stride, xenix have file locking, but no ftruncate. - This mess will do. */ - close (open (inname, O_CREAT | O_TRUNC | O_RDWR, 0666)); -#else ftruncate (indesc, 0L); -#endif /* STRIDE or XENIX */ } #endif /* MAIL_USE_SYSTEM_LOCK */ @@ -533,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! */ @@ -688,6 +677,7 @@ xmalloc (size) #include #endif #include +#include #define NOTOK (-1) #define OK 0 @@ -702,7 +692,7 @@ char Errmsg[200]; /* POP errors, at least, can exceed the original length of 80. */ /* - * The full legal syntax for a POP mailbox specification for movemail + * The full valid syntax for a POP mailbox specification for movemail * is "po:username:hostname". The ":hostname" is optional; if it is * omitted, the MAILHOST environment variable will be consulted. Note * that by the time popmail() is called the "po:" has been stripped @@ -928,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); } @@ -937,7 +936,7 @@ int mbx_delimit_end (mbf) FILE *mbf; { - if (putc ('\037', mbf) == EOF) + if (putc ('\n', mbf) == EOF) return (NOTOK); return (OK); }