Korrektur MPFire CGI
[people/pmueller/ipfire-2.x.git] / src / misc-progs / syslogdctrl.c
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$
9  *
10  * Edited by the IPFire Team to change var log messages 
11  */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <string.h>
17 #include <sys/stat.h>
18 #include <sys/types.h>
19 #include <fcntl.h>
20 #include <signal.h>
21 #include <errno.h>
22 #include "libsmooth.h"
23 #include "setuid.h"
24
25 #define ERR_ANY 1
26 #define ERR_SETTINGS 2    /* error in settings file */
27 #define ERR_ETC 3         /* error with /etc permissions */
28 #define ERR_CONFIG 4      /* error updated sshd_config */
29 #define ERR_SYSLOG 5      /* error restarting syslogd */
30
31 int main(void)
32 {
33    char buffer[STRING_SIZE], hostname[STRING_SIZE], varmessages[STRING_SIZE];
34    int config_fd,rc,fd,pid;
35    struct stat st;
36    struct keyvalue *kv = NULL;
37    memset(buffer, 0, STRING_SIZE);
38    memset(hostname, 0, STRING_SIZE);
39    memset(varmessages, 0, STRING_SIZE);
40
41    if (!(initsetuid()))
42       exit(1);
43
44
45    /* Read in and verify config */
46    kv=initkeyvalues();
47
48    if (!readkeyvalues(kv, "/logging/settings"))
49    {
50       fprintf(stderr, "Cannot read syslog settings\n");
51       exit(ERR_SETTINGS);
52    }
53
54    if (!findkey(kv, "ENABLE_REMOTELOG", buffer))
55    {
56       fprintf(stderr, "Cannot read ENABLE_REMOTELOG\n");
57       exit(ERR_SETTINGS);
58    }
59
60    if (!findkey(kv, "REMOTELOG_ADDR", hostname))
61    {
62       fprintf(stderr, "Cannot read REMOTELOG_ADDR\n");
63       exit(ERR_SETTINGS);
64    }
65    
66    if (!findkey(kv, "VARMESSAGES", varmessages))
67    {
68       fprintf(stderr, "Cannot read VARMESSAGES\n");
69       exit(ERR_SETTINGS);
70    }
71
72    if (strspn(hostname, VALID_FQDN) != strlen(hostname))
73    {
74       fprintf(stderr, "Bad REMOTELOG_ADDR: %s\n", hostname);
75       exit(ERR_SETTINGS);
76    }
77
78    freekeyvalues(kv);
79
80
81    /* If anyone other than root can write to /etc this would be totally
82     * insecure - same if anyone other than root owns /etc, as they could
83     * change the file mode to give themselves or anyone else write access. */
84
85    if(lstat("/etc",&st))
86    {
87       perror("Unable to stat /etc");
88       exit(ERR_ETC);
89    }
90    if(!S_ISDIR(st.st_mode))
91    {
92       fprintf(stderr, "/etc is not a directory?!\n");
93       exit(ERR_ETC);
94    }
95    if ( st.st_uid != 0  ||  st.st_mode & S_IWOTH ||
96       ((st.st_gid != 0) && (st.st_mode & S_IWGRP)) )
97    {
98       fprintf(stderr, "/etc is owned/writable by non-root users\n");
99       exit(ERR_ETC);
100    }
101
102    /* O_CREAT with O_EXCL will make open() fail if the file already exists -
103     * mostly to prevent 2 copies running at once */
104    if ((config_fd = open( "/etc/syslog.conf.new", O_WRONLY|O_CREAT|O_EXCL, 0644 )) == -1 )
105    {
106       perror("Unable to open new config file");
107       exit(ERR_CONFIG);
108    }
109
110    if (!strcmp(buffer,"on"))
111       snprintf(buffer, STRING_SIZE - 1, "/bin/sed -e 's/^#\\?\\(\\*\\.\\*[[:blank:]]\\+@\\).\\+$/\\1%s/' /etc/syslog.conf >&%d", hostname, config_fd );
112    else
113       snprintf(buffer, STRING_SIZE - 1, "/bin/sed -e 's/^#\\?\\(\\*\\.\\*[[:blank:]]\\+@.\\+\\)$/#\\1/' /etc/syslog.conf >&%d", config_fd );
114       
115       snprintf(buffer, STRING_SIZE - 1, "&& /bin/sed -e 's/*.\/var\/log\/messages/%s \/var\/log\/messages/' /etc/syslog.conf >&%d", varmessages, config_fd );
116
117    /* if the return code isn't 0 failsafe */
118    if ((rc = unpriv_system(buffer,99,99)) != 0)
119    {
120       fprintf(stderr, "sed returned bad exit code: %d\n", rc);
121       close(config_fd);
122       unlink("/etc/syslog.conf.new");
123       exit(ERR_CONFIG);
124    }
125    close(config_fd);
126    if (rename("/etc/syslog.conf.new /etc/syslog.conf") == -1)
127    {
128       perror("Unable to replace old config file");
129       unlink("/etc/syslog.conf.new");
130       exit(ERR_CONFIG);
131    }
132
133
134    /* Get syslogd to read the new config file */
135    if ((fd = open("/var/run/syslogd.pid", O_RDONLY)) == -1)
136    {
137       if(errno == ENOENT)
138       {
139          /* pid file doesn't exists.. restart syslog */
140          if((rc = safe_system("/usr/sbin/syslogd u syslogd -m 0")) == 0 )
141             return 0;
142          else
143          {
144             fprintf(stderr,
145                "Unable to restart syslogd - returned exit code %d\n", rc);
146             exit(ERR_SYSLOG);
147          }
148       } else {
149          /* Something odd is going on, failsafe */
150          perror("Unable to open pid file");
151          exit(ERR_SYSLOG);
152       }
153    }
154
155    memset(buffer, 0, STRING_SIZE);
156    if (read(fd, buffer, STRING_SIZE - 1) == -1)
157    {
158       close(fd);
159       perror("Couldn't read from pid file");
160       exit(ERR_SYSLOG);
161    }
162    close(fd);
163    /* strtol does sanity checks that atoi doesn't do */
164    errno = 0;
165    pid = (int)strtol(buffer, (char **)NULL, 10);
166    if (errno || pid <= 1)
167    {
168       fprintf(stderr, "Bad pid value\n");
169       exit(ERR_SYSLOG);
170    }
171    if (kill(pid, SIGHUP) == -1)
172    {
173       fprintf(stderr, "Unable to send SIGHUP\n");
174       exit(ERR_SYSLOG);
175    }
176
177    return 0;
178 }