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