]>
Commit | Line | Data |
---|---|---|
cd1a2927 MT |
1 | /* This file is part of the IPCop Firewall.\r |
2 | *\r | |
3 | * This program is distributed under the terms of the GNU General Public\r | |
4 | * Licence. See the file COPYING for details.\r | |
5 | *\r | |
6 | * Copyright (C) 2003-07-12 Robert Kerr <rkerr@go.to>\r | |
7 | *\r | |
8 | * $Id: logwatch.c,v 1.2 2003/12/11 11:25:54 riddles Exp $\r | |
9 | *\r | |
10 | */\r | |
11 | \r | |
12 | #include <stdio.h>\r | |
13 | #include <unistd.h>\r | |
14 | #include <stdlib.h>\r | |
15 | #include <string.h>\r | |
16 | #include <grp.h>\r | |
17 | #include <pwd.h>\r | |
18 | #include <sys/types.h>\r | |
19 | #include "libsmooth.h"\r | |
20 | #include "setuid.h"\r | |
21 | \r | |
22 | /* Lots of distros just run logwatch as root from cron, but logwatch doesn't\r | |
23 | * need any root privs, just the ability to access it's filter scripts\r | |
24 | * (/etc/log.d/) and the log files (under /var/log/). By creating a logwatch\r | |
25 | * user and group and ensuring it has read access to the logs we can run\r | |
26 | * logwatch unprivileged. Apart from the principle of least privilege running\r | |
27 | * logwatch as root turns out to be doubly a bad idea because a flaw in the way\r | |
28 | * it works:\r | |
29 | *\r | |
30 | * http://www.securityfocus.com/archive/1/327833/2003-07-01/2003-07-07/0\r | |
31 | *\r | |
32 | * This wrapper program should be run as root, but not installed setuid root,\r | |
33 | * it's basic aim is to allow a root cron job to safely run logcheck; as such\r | |
34 | * it will drop privileges, becoming the locheck user & group then run\r | |
35 | * logcheck. In many ways this is much the same as getting cron to run\r | |
36 | * su -s /etc/log.d/scripts/logwatch.pl\r | |
37 | * the wrapper however is able to read configuration info from /var/ipcop and\r | |
38 | * pass the correct args to logwatch\r | |
39 | */\r | |
40 | \r | |
41 | int main(void)\r | |
42 | {\r | |
43 | char buffer[STRING_SIZE];\r | |
44 | struct keyvalue *kv = NULL;\r | |
45 | struct passwd *pw;\r | |
46 | gid_t groups[2];\r | |
47 | char * argv[4];\r | |
48 | \r | |
49 | if(getuid())\r | |
50 | {\r | |
51 | fprintf(stderr, "logwatch should be ran by root\n");\r | |
52 | exit(1);\r | |
53 | }\r | |
54 | \r | |
55 | /* Read in and verify config */\r | |
56 | kv=initkeyvalues();\r | |
57 | \r | |
58 | if (!readkeyvalues(kv, CONFIG_ROOT "/logging/settings"))\r | |
59 | {\r | |
60 | fprintf(stderr, "Cannot read syslog settings\n");\r | |
61 | exit(1);\r | |
62 | }\r | |
63 | \r | |
64 | if (!findkey(kv, "LOGWATCH_LEVEL", buffer))\r | |
65 | {\r | |
66 | fprintf(stderr, "Cannot read LOGWATCH_LEVEL\n");\r | |
67 | exit(1);\r | |
68 | }\r | |
69 | \r | |
70 | if (strcmp(buffer,"Low") && strcmp(buffer,"Med") && strcmp(buffer,"High"))\r | |
71 | {\r | |
72 | fprintf(stderr, "Bad LOGWATCH_LEVEL: %s\n", buffer);\r | |
73 | exit(1);\r | |
74 | }\r | |
75 | \r | |
76 | freekeyvalues(kv);\r | |
77 | \r | |
78 | \r | |
79 | /* lookup logwatch user */\r | |
80 | if(!(pw = getpwnam("logwatch")))\r | |
81 | {\r | |
82 | fprintf(stderr,"Couldn't find logwatch user.\n");\r | |
83 | exit(1);\r | |
84 | }\r | |
85 | /* paranoia... */\r | |
86 | memset(pw->pw_passwd, 0, strlen(pw->pw_passwd));\r | |
87 | endpwent();\r | |
88 | \r | |
89 | /* more paranoia */\r | |
90 | if(!pw->pw_uid || !pw->pw_gid)\r | |
91 | {\r | |
92 | fprintf(stderr,"logwatch user appears to be UID or GID 0, aborting.\n");\r | |
93 | exit(1);\r | |
94 | }\r | |
95 | \r | |
96 | /* drop privs */\r | |
97 | groups[0] = groups[1] = pw->pw_gid;\r | |
98 | if (setgroups(1,groups)) { perror("Couldn't clear group list"); exit(1); }\r | |
99 | if (setgid(pw->pw_gid)) { perror("Couldn't setgid(logwatch)"); exit(1); }\r | |
100 | if (setuid(pw->pw_uid)) { perror("Couldn't setuid(logwatch)"); exit(1); }\r | |
101 | \r | |
102 | /* ok, spawn logwatch */\r | |
103 | argv[0] = "logwatch.pl";\r | |
104 | argv[1] = "--detail";\r | |
105 | argv[2] = buffer;\r | |
106 | argv[3] = NULL;\r | |
107 | execve("/etc/log.d/scripts/logwatch.pl", argv, trusted_env);\r | |
108 | \r | |
109 | /* shouldn't get here - execve replaces current running process */\r | |
110 | perror("logwatch: execve failed");\r | |
111 | exit(1);\r | |
112 | }\r |