--- /dev/null
+/* This file is part of the IPCop Firewall.\r
+ *\r
+ * This program is distributed under the terms of the GNU General Public\r
+ * Licence. See the file COPYING for details.\r
+ *\r
+ * Copyright (C) 2003-07-12 Robert Kerr <rkerr@go.to>\r
+ *\r
+ * $Id: logwatch.c,v 1.2 2003/12/11 11:25:54 riddles Exp $\r
+ *\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <unistd.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <grp.h>\r
+#include <pwd.h>\r
+#include <sys/types.h>\r
+#include "libsmooth.h"\r
+#include "setuid.h"\r
+\r
+/* Lots of distros just run logwatch as root from cron, but logwatch doesn't\r
+ * need any root privs, just the ability to access it's filter scripts\r
+ * (/etc/log.d/) and the log files (under /var/log/). By creating a logwatch\r
+ * user and group and ensuring it has read access to the logs we can run\r
+ * logwatch unprivileged. Apart from the principle of least privilege running\r
+ * logwatch as root turns out to be doubly a bad idea because a flaw in the way\r
+ * it works:\r
+ *\r
+ * http://www.securityfocus.com/archive/1/327833/2003-07-01/2003-07-07/0\r
+ *\r
+ * This wrapper program should be run as root, but not installed setuid root,\r
+ * it's basic aim is to allow a root cron job to safely run logcheck; as such\r
+ * it will drop privileges, becoming the locheck user & group then run\r
+ * logcheck. In many ways this is much the same as getting cron to run\r
+ * su -s /etc/log.d/scripts/logwatch.pl\r
+ * the wrapper however is able to read configuration info from /var/ipcop and\r
+ * pass the correct args to logwatch\r
+ */\r
+\r
+int main(void)\r
+{\r
+ char buffer[STRING_SIZE];\r
+ struct keyvalue *kv = NULL;\r
+ struct passwd *pw;\r
+ gid_t groups[2];\r
+ char * argv[4];\r
+\r
+ if(getuid())\r
+ {\r
+ fprintf(stderr, "logwatch should be ran by root\n");\r
+ exit(1);\r
+ }\r
+\r
+ /* Read in and verify config */\r
+ kv=initkeyvalues();\r
+\r
+ if (!readkeyvalues(kv, CONFIG_ROOT "/logging/settings"))\r
+ {\r
+ fprintf(stderr, "Cannot read syslog settings\n");\r
+ exit(1);\r
+ }\r
+\r
+ if (!findkey(kv, "LOGWATCH_LEVEL", buffer))\r
+ {\r
+ fprintf(stderr, "Cannot read LOGWATCH_LEVEL\n");\r
+ exit(1);\r
+ }\r
+\r
+ if (strcmp(buffer,"Low") && strcmp(buffer,"Med") && strcmp(buffer,"High"))\r
+ {\r
+ fprintf(stderr, "Bad LOGWATCH_LEVEL: %s\n", buffer);\r
+ exit(1);\r
+ }\r
+\r
+ freekeyvalues(kv);\r
+\r
+\r
+ /* lookup logwatch user */\r
+ if(!(pw = getpwnam("logwatch")))\r
+ {\r
+ fprintf(stderr,"Couldn't find logwatch user.\n");\r
+ exit(1);\r
+ }\r
+ /* paranoia... */\r
+ memset(pw->pw_passwd, 0, strlen(pw->pw_passwd));\r
+ endpwent();\r
+\r
+ /* more paranoia */\r
+ if(!pw->pw_uid || !pw->pw_gid)\r
+ {\r
+ fprintf(stderr,"logwatch user appears to be UID or GID 0, aborting.\n");\r
+ exit(1);\r
+ }\r
+\r
+ /* drop privs */\r
+ groups[0] = groups[1] = pw->pw_gid;\r
+ if (setgroups(1,groups)) { perror("Couldn't clear group list"); exit(1); }\r
+ if (setgid(pw->pw_gid)) { perror("Couldn't setgid(logwatch)"); exit(1); }\r
+ if (setuid(pw->pw_uid)) { perror("Couldn't setuid(logwatch)"); exit(1); }\r
+\r
+ /* ok, spawn logwatch */\r
+ argv[0] = "logwatch.pl";\r
+ argv[1] = "--detail";\r
+ argv[2] = buffer;\r
+ argv[3] = NULL;\r
+ execve("/etc/log.d/scripts/logwatch.pl", argv, trusted_env);\r
+\r
+ /* shouldn't get here - execve replaces current running process */\r
+ perror("logwatch: execve failed");\r
+ exit(1);\r
+}\r