Problems are listed in approximate order of priority.
-- Re-visit nametemplate support. Currently, we use
- symbolic links in our temporary directory for this. When
- using /tmp, this may have security implementations and
- introduce race conditions.
-
- Fix the "unexpected EXPUNGE" IMAP bug.
{
dprint(1, (debugfile, "oldfile: %s\t newfile: %s\n",
a->filename, newfile));
- if (symlink (a->filename, newfile) == -1)
+ if (safe_symlink (a->filename, newfile) == -1)
{
if (!mutt_yesorno ("Can't match nametemplate, continue?", 1))
goto bailout;
{
dprint(1, (debugfile, "oldfile: %s\t newfile: %s\n",
a->filename, newfile));
- if (symlink (a->filename, newfile) == -1)
+ if (safe_symlink (a->filename, newfile) == -1)
{
if (!mutt_yesorno ("Can't match nametemplate, continue?", 1))
goto bailout;
if (fp == NULL)
{
/* send case: the file is already there */
- if (symlink (a->filename, tempfile) == -1)
+ if (safe_symlink (a->filename, tempfile) == -1)
{
if (mutt_yesorno ("Can't match nametemplate, continue?", 1) == M_YES)
strfcpy (tempfile, a->filename, sizeof (tempfile));
{
if (!fp)
{
- if (symlink(a->filename, newfile) == -1)
+ if (safe_symlink(a->filename, newfile) == -1)
{
if (mutt_yesorno ("Can't match nametemplate, continue?", 1) != M_YES)
{
FREE(&_src);
}
+static int
+compare_stat (struct stat *osb, struct stat *nsb)
+{
+ if (osb->st_dev != nsb->st_dev || osb->st_ino != nsb->st_ino ||
+ osb->st_rdev != nsb->st_rdev)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+int safe_symlink(const char *oldpath, const char *newpath)
+{
+ struct stat osb, nsb;
+
+ if(!oldpath || !newpath)
+ return -1;
+
+ if(unlink(newpath) == -1 && errno != ENOENT)
+ return -1;
+
+ if(symlink(oldpath, newpath) == -1)
+ return -1;
+
+ if(stat(oldpath, &osb) == -1 || stat(newpath, &nsb) == -1
+ || compare_stat(&osb, &nsb) == -1)
+ {
+ unlink(newpath);
+ return -1;
+ }
+
+ return 0;
+}
+
int safe_open (const char *path, int flags)
{
struct stat osb, nsb;
/* make sure the file is not symlink */
if (lstat (path, &osb) < 0 || fstat (fd, &nsb) < 0 ||
- osb.st_dev != nsb.st_dev || osb.st_ino != nsb.st_ino ||
- osb.st_rdev != nsb.st_rdev)
+ compare_stat(&osb, &nsb) == -1)
{
dprint (1, (debugfile, "safe_open(): %s is a symlink!\n", path));
close (fd);
void safe_free (void **);
int safe_open (const char *, int);
+int safe_symlink (const char *, const char *);
FILE *safe_fopen (const char *, const char *);
ADDRESS *alias_reverse_lookup (ADDRESS *);