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). --- parser.y | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) (limited to 'parser.y') 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