From 7bbad4f8de74ef60f19137230c38100787fd982b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Fonseca?= Date: Tue, 15 Feb 2005 17:15:38 +0000 Subject: Enforce strict permissions on configuration file (Tiago Macambira). --- NEWS | 4 ++- configure.ac | 2 ++ parser.y | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 84 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 13d47c9..729de80 100644 --- a/NEWS +++ b/NEWS @@ -8,7 +8,9 @@ News * Do not attempt to authenticate if no username/password is given. - * Several configuration enhancements (SASAJIMA, Dirk Tilger). + * Several configuration fixes/enhancements (SASAJIMA and Dirk Tilger). + + * Enforce strict permissions on configuration file (Tiago Macambira). * Version 0.5.0 (2003-11-14): diff --git a/configure.ac b/configure.ac index a752f73..30aea20 100644 --- a/configure.ac +++ b/configure.ac @@ -44,5 +44,7 @@ AC_SUBST( sysconfdir ) jrf_FUNC_GETOPT +AC_CHECK_FUNCS([getuid geteuid]) + AC_CONFIG_FILES([Makefile]) AC_OUTPUT diff --git a/parser.y b/parser.y index 437adbf..a13a200 100644 --- a/parser.y +++ b/parser.y @@ -7,10 +7,18 @@ */ +#include "config.h" + #include #include #include #include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif #include @@ -125,6 +133,73 @@ void yyerror (const char *s) exit(EX_CONFIG); } +/** + * Check that a configuration file is secure. + * + * \param securecheck if set to 1 strict file permission tests will be run. + * + * \return 0 if everything is OK, -1 in case of error + * + */ +int rcfile_check(const char *pathname, const int securecheck) +{ +#ifndef __EMX__ + struct stat statbuf; + + errno = 0; + + /* special case useful for debugging purposes */ + if (strcmp("/dev/null", pathname) == 0) + return 0; + + /* pass through the special name for stdin */ + if (strcmp("-", pathname) == 0) + return 0; + + /* the run control file must have the same uid as the REAL uid of this + * process, it must have permissions no greater than 600, and it must + * not be a symbolic link. We check these conditions here. + */ + if (lstat(pathname, &statbuf) < 0) { + if (errno == ENOENT) + return 0; + else { + fprintf(stderr, "lstat: %s: %s\n", pathname, strerror(errno)); + return -1; + } + } + + if (!securecheck) + return 0; + + if (!S_ISREG(statbuf.st_mode)) + { + fprintf(stderr, "File %s must be a regular file.\n", pathname); + return -1; + } + +#ifndef __BEOS__ + if (statbuf.st_mode & (S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH | S_IXOTH)) + { + fprintf(stderr, "File %s must have no more than -rwx--x--- (0710) permissions.\n", pathname); + return -1; + } +#endif /* !__BEOS__ */ + +#ifdef HAVE_GETEUID + if (statbuf.st_uid != geteuid()) +#else + if (statbuf.st_uid != getuid()) +#endif /* HAVE_GETEUID */ + { + fprintf(stderr, "File %s must be owned by you.\n", pathname); + return -1; + } +#endif + return 0; +} + + #define RCFILE "esmtprc" #define DOT_RCFILE "." RCFILE #define ETC_RCFILE SYSCONFDIR "/" RCFILE @@ -157,8 +232,11 @@ void rcfile_parse(const char *_rcfile) if (dot_rcfile[strlen(dot_rcfile) - 1] != '/') strcat(dot_rcfile, "/"); strcat(dot_rcfile, DOT_RCFILE); - rcfile = dot_rcfile; + + if (rcfile_check(rcfile, 1) < 0) + goto failure; + if(!(yyin = fopen(rcfile, "r"))) { if(errno == ENOENT) -- cgit v1.2.3