From c85fbf59a201b6475c2f957428b6ab964c02eabc Mon Sep 17 00:00:00 2001 From: Thomas Roessler Date: Sun, 6 Sep 1998 10:05:41 +0000 Subject: [PATCH] [patch-0.94.5i.tlr.safe_symlink.1] Introduce safe_symlink() for /tmp-safe symlinking in the nametemplate code. --- TODO | 5 ----- attach.c | 8 ++++---- lib.c | 38 ++++++++++++++++++++++++++++++++++++-- protos.h | 1 + 4 files changed, 41 insertions(+), 11 deletions(-) diff --git a/TODO b/TODO index c6489b105..c46d082af 100644 --- a/TODO +++ b/TODO @@ -1,10 +1,5 @@ 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. diff --git a/attach.c b/attach.c index 5492d61a4..e9ee861fe 100644 --- a/attach.c +++ b/attach.c @@ -106,7 +106,7 @@ int mutt_compose_attachment (BODY *a) { 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; @@ -228,7 +228,7 @@ int mutt_edit_attachment (BODY *a) { 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; @@ -360,7 +360,7 @@ int mutt_view_attachment (FILE *fp, BODY *a, int flag) 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)); @@ -807,7 +807,7 @@ int mutt_print_attachment (FILE *fp, BODY *a) { 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) { diff --git a/lib.c b/lib.c index 45d901d35..3d889c007 100644 --- a/lib.c +++ b/lib.c @@ -656,6 +656,41 @@ void mutt_expand_fmt (char *dest, size_t destlen, const char *fmt, const char *s 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; @@ -666,8 +701,7 @@ int safe_open (const char *path, int flags) /* 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); diff --git a/protos.h b/protos.h index b349dca42..ad2583e2b 100644 --- a/protos.h +++ b/protos.h @@ -282,6 +282,7 @@ void safe_realloc (void **, size_t); 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 *); -- 2.40.0