1 // +------------------------------------------------------------------+
2 // | ____ _ _ __ __ _ __ |
3 // | / ___| |__ ___ ___| | __ | \/ | |/ / |
4 // | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
5 // | | |___| | | | __/ (__| < | | | | . \ |
6 // | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
8 // | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
9 // +------------------------------------------------------------------+
11 // This file is part of Check_MK.
12 // The official homepage is at http://mathias-kettner.de/check_mk.
14 // check_mk is free software; you can redistribute it and/or modify it
15 // under the terms of the GNU General Public License as published by
16 // the Free Software Foundation in version 2. check_mk is distributed
17 // in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
18 // out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
19 // PARTICULAR PURPOSE. See the GNU General Public License for more de-
20 // ails. You should have received a copy of the GNU General Public
21 // License along with GNU Make; see the file COPYING. If not, write
22 // to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
23 // Boston, MA 02110-1301 USA.
25 /* This small helper program is intended to be installed SUID root.
26 Otherwise it is pointless. It creates a UDP socket with port 514.
27 This is a priviledged operation. Then it drops the priviledges,
28 moves that port to file descriptor 3 and executes the mkeventd.
30 That can then simply use filedescriptor 3 and receive syslog
33 #include <netinet/in.h>
34 #include <sys/socket.h>
40 #define SYSLOG_PORT 514
41 #define SNMPTRAP_PORT 162
43 #define PROGRAM "mkeventd"
45 // Example command line:
46 // mkeventd_open514 --syslog --syslog-fd 3 --syslog-tcp --syslog-tcp-fd 4
47 // --snmptrap --snmptrap-fd 5
49 int main(int argc
, char **argv
) {
51 int do_syslog_tcp
= 0;
55 int syslog_tcp_fd
= -1;
60 for (i
= 1; i
< argc
; i
++) {
61 if (strcmp(argv
[i
], "--syslog") == 0) {
63 } else if (strcmp(argv
[i
], "--syslog-tcp") == 0) {
65 } else if (strcmp(argv
[i
], "--snmptrap") == 0) {
67 } else if (strcmp(argv
[i
], "--syslog-fd") == 0) {
68 syslog_fd
= atoi(argv
[i
+ 1]);
69 } else if (strcmp(argv
[i
], "--syslog-tcp-fd") == 0) {
70 syslog_tcp_fd
= atoi(argv
[i
+ 1]);
71 } else if (strcmp(argv
[i
], "--snmptrap-fd") == 0) {
72 snmptrap_fd
= atoi(argv
[i
+ 1]);
77 if (do_syslog
!= 0 && syslog_fd
> 0) {
80 if (0 > (syslog_sock
= socket(PF_INET
, SOCK_DGRAM
, 0))) {
81 perror("Cannot create UDP socket for syslog");
87 if (0 != setsockopt(syslog_sock
, SOL_SOCKET
, SO_REUSEADDR
, &optval
,
89 perror("Cannot set UDP socket for syslog to SO_REUSEADDR");
93 // Bind it to the port (this requires priviledges)
94 struct sockaddr_in addr
;
95 addr
.sin_family
= AF_INET
;
96 addr
.sin_port
= htons(SYSLOG_PORT
);
97 addr
.sin_addr
.s_addr
= 0;
98 if (0 != bind(syslog_sock
, reinterpret_cast<struct sockaddr
*>(&addr
),
101 "Cannot bind UDP socket for syslog to port "
102 "(Is SUID bit set on mkeventd_open514? Is \"nosuid\" not set on the filesystem?)");
106 // Make sure it is at the correct FD
107 if (syslog_sock
!= 0 && syslog_sock
!= syslog_fd
) {
108 dup2(syslog_sock
, syslog_fd
);
114 if (do_syslog_tcp
!= 0 && syslog_tcp_fd
> 0) {
117 if (0 > (syslog_tcp_sock
= socket(PF_INET
, SOCK_STREAM
, 0))) {
118 perror("Cannot create TCP socket for syslog-tcp");
124 if (0 != setsockopt(syslog_tcp_sock
, SOL_SOCKET
, SO_REUSEADDR
, &optval
,
126 perror("Cannot set TCP socket for syslog-tcp to SO_REUSEADDR");
130 // Bind it to the port (this requires priviledges)
131 struct sockaddr_in addr
;
132 addr
.sin_family
= AF_INET
;
133 addr
.sin_port
= htons(SYSLOG_PORT
);
134 addr
.sin_addr
.s_addr
= 0;
135 if (0 != bind(syslog_tcp_sock
,
136 reinterpret_cast<struct sockaddr
*>(&addr
),
139 "Cannot bind TCP socket for syslog-tcp to port "
140 "(Is SUID bit set on mkeventd_open514? Is \"nosuid\" not set on the filesystem?)");
144 // Make sure it is at the correct FD
145 if (syslog_tcp_sock
!= 0 && syslog_tcp_sock
!= syslog_tcp_fd
) {
146 dup2(syslog_tcp_sock
, syslog_tcp_fd
);
147 close(syslog_tcp_sock
);
152 if (do_snmptrap
!= 0 && snmptrap_fd
> 0) {
155 if (0 > (snmptrap_sock
= socket(PF_INET
, SOCK_DGRAM
, 0))) {
156 perror("Cannot create UDP socket for snmptrap");
162 if (0 != setsockopt(snmptrap_sock
, SOL_SOCKET
, SO_REUSEADDR
, &optval
,
164 perror("Cannot set UDP socket for snmptrap to SO_REUSEADDR");
168 // Bind it to the port (this requires priviledges)
169 struct sockaddr_in addr
;
170 addr
.sin_family
= AF_INET
;
171 addr
.sin_port
= htons(SNMPTRAP_PORT
);
172 addr
.sin_addr
.s_addr
= 0;
173 if (0 != bind(snmptrap_sock
, reinterpret_cast<struct sockaddr
*>(&addr
),
176 "Cannot bind UDP socket for snmptrap to port "
177 "(Is SUID bit set on mkeventd_open514? Is \"nosuid\" not set on the filesystem?)");
181 // Make sure it is at the correct FD
182 if (snmptrap_sock
!= 0 && snmptrap_sock
!= snmptrap_fd
) {
183 dup2(snmptrap_sock
, snmptrap_fd
);
184 close(snmptrap_sock
);
189 if (getuid() != geteuid()) {
190 if (0 != seteuid(getuid())) {
191 perror("Cannot drop priviledges");
196 // Execute the actual program that needs access to the
197 // socket. We take the path from argv[0]
198 char *last_slash
= argv
[0];
199 char *scan
= argv
[0];
202 last_slash
= scan
+ 1;
207 bzero(&newpath
, 512);
208 int len_to_copy
= last_slash
- argv
[0];
209 if (len_to_copy
>= 512) {
213 memcpy(newpath
, argv
[0], len_to_copy
);
214 strncpy(newpath
+ len_to_copy
, PROGRAM
, 511 - len_to_copy
);
215 execv(newpath
, argv
);
216 perror("Cannot execute mkeventd");