]> git.ipfire.org Git - ipfire-2.x.git/blobdiff - src/misc-progs/logwatch.c
git-svn-id: http://svn.ipfire.org/svn/ipfire/IPFire/source@16 ea5c0bd1-69bd-2848...
[ipfire-2.x.git] / src / misc-progs / logwatch.c
diff --git a/src/misc-progs/logwatch.c b/src/misc-progs/logwatch.c
new file mode 100644 (file)
index 0000000..8b78a68
--- /dev/null
@@ -0,0 +1,112 @@
+/* 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