source: trunk/src/sh_xfer_syslog.c@ 583

Last change on this file since 583 was 583, checked in by katerina, 27 hours ago

Fix for ticket #471 (autoreconf throws warnings/errors).

File size: 11.6 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 1999, 2000 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14/* GNU General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU General Public License */
17/* along with this program; if not, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20#include "config_xor.h"
21
22#include <string.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <syslog.h>
26
27/* Must be early on FreeBSD
28 */
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <netdb.h>
32#include <netinet/in.h>
33
34#if HAVE_SYS_TIME_H
35#include <sys/time.h>
36#endif
37#include <time.h>
38
39#include <unistd.h>
40#include <fcntl.h>
41
42#ifdef SH_WITH_SERVER
43
44#include "samhain.h"
45#include "sh_tools.h"
46#include "sh_utils.h"
47#include "sh_ipvx.h"
48
49#undef FIL__
50#define FIL__ _("sh_xfer_syslog.c")
51
52#ifdef INET_SYSLOG
53
54extern void sh_xfer_printerr(char * str, int errnum, unsigned int port, int line);
55extern int sh_xfer_syslog_sock[SH_SOCKMAX];
56extern int sh_xfer_syslog_sock_n;
57extern int SH_MINSOCK;
58
59/* Unlike Linux / FreeBSD, most systems don't define the stuff below
60 * in syslog.h
61 */
62
63#ifndef LOG_FAC
64#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3)
65#endif
66
67#ifndef LOG_PRI
68#define LOG_PRI(p) ((p) & LOG_PRIMASK)
69#endif
70
71typedef struct sh_code {
72 char *c_name;
73 int c_val;
74} SH_CODE;
75
76SH_CODE sh_facilitynames[] =
77{
78#ifdef LOG_AUTH
79 { N_("auth"), LOG_AUTH },
80#endif
81#ifdef LOG_AUTHPRIV
82 { N_("authpriv"), LOG_AUTHPRIV },
83#endif
84#ifdef LOG_CRON
85 { N_("cron"), LOG_CRON },
86#endif
87#ifdef LOG_DAEMON
88 { N_("daemon"), LOG_DAEMON },
89#endif
90#ifdef LOG_FTP
91 { N_("ftp"), LOG_FTP },
92#endif
93#ifdef LOG_KERN
94 { N_("kern"), LOG_KERN },
95#endif
96#ifdef LOG_LPR
97 { N_("lpr"), LOG_LPR },
98#endif
99#ifdef LOG_MAIL
100 { N_("mail"), LOG_MAIL },
101#endif
102#ifdef INTERNAL_MARK
103 { N_("mark"), INTERNAL_MARK }, /* INTERNAL */
104#endif
105#ifdef LOG_NEWS
106 { N_("news"), LOG_NEWS },
107#endif
108#ifdef LOG_AUTH
109 { N_("security"), LOG_AUTH }, /* DEPRECATED */
110#endif
111#ifdef LOG_SYSLOG
112 { N_("syslog"), LOG_SYSLOG },
113#endif
114#ifdef LOG_USER
115 { N_("user"), LOG_USER },
116#endif
117#ifdef LOG_UUCP
118 { N_("uucp"), LOG_UUCP },
119#endif
120#ifdef LOG_LOCAL0
121 { N_("local0"), LOG_LOCAL0 },
122#endif
123#ifdef LOG_LOCAL1
124 { N_("local1"), LOG_LOCAL1 },
125#endif
126#ifdef LOG_LOCAL2
127 { N_("local2"), LOG_LOCAL2 },
128#endif
129#ifdef LOG_LOCAL3
130 { N_("local3"), LOG_LOCAL3 },
131#endif
132#ifdef LOG_LOCAL4
133 { N_("local4"), LOG_LOCAL4 },
134#endif
135#ifdef LOG_LOCAL5
136 { N_("local5"), LOG_LOCAL5 },
137#endif
138#ifdef LOG_LOCAL6
139 { N_("local6"), LOG_LOCAL6 },
140#endif
141#ifdef LOG_LOCAL7
142 { N_("local7"), LOG_LOCAL7 },
143#endif
144 { NULL, -1 }
145};
146
147
148SH_CODE sh_prioritynames[] =
149{
150#ifdef LOG_ALERT
151 { N_("alert"), LOG_ALERT },
152#endif
153#ifdef LOG_CRIT
154 { N_("crit"), LOG_CRIT },
155#endif
156#ifdef LOG_DEBUG
157 { N_("debug"), LOG_DEBUG },
158#endif
159#ifdef LOG_EMERG
160 { N_("emerg"), LOG_EMERG },
161#endif
162#ifdef LOG_ERR
163 { N_("err"), LOG_ERR },
164#endif
165#ifdef LOG_ERR
166 { N_("error"), LOG_ERR }, /* DEPRECATED */
167#endif
168#ifdef LOG_INFO
169 { N_("info"), LOG_INFO },
170#endif
171#ifdef INTERNAL_NOPRI
172 { N_("none"), INTERNAL_NOPRI }, /* INTERNAL */
173#endif
174#ifdef LOG_NOTICE
175 { N_("notice"), LOG_NOTICE },
176#endif
177#ifdef LOG_EMERG
178 { N_("panic"), LOG_EMERG }, /* DEPRECATED */
179#endif
180#ifdef LOG_WARNING
181 { N_("warn"), LOG_WARNING }, /* DEPRECATED */
182#endif
183#ifdef LOG_WARNING
184 { N_("warning"), LOG_WARNING },
185#endif
186 { NULL, -1 }
187};
188
189static int enable_syslog_socket = S_FALSE;
190
191int sh_xfer_recv_syslog_socket (int fd)
192{
193 static time_t return_next = 0;
194 int priority = 0;
195 int fac, pri;
196 int i;
197 char * cfac = NULL;
198 char * cpri = NULL;
199 int res;
200 char * tmp;
201 char * bptr;
202 char * ptr = NULL;
203 char buf[1048];
204 struct sockaddr_in from;
205 char errbuf[SH_ERRBUF_SIZE];
206
207 struct sh_sockaddr ss;
208 struct sockaddr * sa = (struct sockaddr *) &from;
209 char namebuf[SH_BUFSIZE];
210
211 /* The 6th argument in recvfrom is *socklen_t in Linux and *BSD,
212 * but *int everywhere else. Because socklen_t is unsigned int, there
213 * should be no problem as long as sizeof(struct sockaddr_in) < INT_MAX ...
214 */
215 unsigned int fromlen = sizeof(from);
216
217 if (enable_syslog_socket == S_FALSE)
218 return 0;
219
220 SL_ENTER(_("sh_xfer_recv_syslog_socket"));
221
222 if (return_next > 0)
223 {
224 if ( (time(NULL) - return_next) < 2)
225 SL_RETURN( 0, _("sh_xfer_recv_syslog_socket"));
226 else
227 return_next = 0;
228 }
229
230 res = recvfrom(fd, buf, 1047, 0, (struct sockaddr *) &from, &fromlen);
231
232 sh_ipvx_save(&ss, sa->sa_family, (struct sockaddr *) &from);
233 sh_ipvx_ntoa(namebuf, sizeof(namebuf), &ss);
234
235 if (res > 0)
236 {
237 res = (res < 1047) ? res : 1047;
238 buf[res] = '\0';
239 if (res > 1 && buf[res-1] == '\n')
240 buf[res-1] = '\0';
241
242 /* here we expect an xml formatted message, thus we don't
243 escape xml special chars (flag == 0) */
244 /* commented out to not escape twice */
245 /* bptr = sh_tools_safe_name(buf, 0); */
246 bptr = buf;
247
248 if (!bptr || !(*bptr))
249 {
250 res = errno;
251 TPT(( 0, FIL__, __LINE__, _("msg=<UDP error: %d>\n"), res));
252 sh_error_handle((-1), FIL__, __LINE__, res, MSG_ERR_SYSLOG,
253 sh_error_message(res, errbuf, sizeof(errbuf)),
254 namebuf);
255 SL_RETURN( (-1), _("sh_xfer_recv_syslog_socket"));
256 }
257
258 TPT(( 0, FIL__, __LINE__, _("msg=<UDP message from %s>\n"), namebuf ));
259
260 ptr = bptr;
261 i = 0;
262 if (*ptr == '<')
263 {
264 ++ptr; ++i;
265 while (i < res &&
266 (unsigned char) *ptr > 47 && (unsigned char) *ptr < 58)
267 {
268 priority = 10 * priority + (*ptr - '0');
269 ++ptr;
270 ++i;
271 }
272 if (*ptr == '>')
273 ++ptr;
274 }
275 fac = LOG_FAC(priority);
276 i = 0;
277 while (sh_facilitynames[i].c_name != NULL)
278 {
279 if (sh_facilitynames[i].c_val == (fac<<3))
280 { cfac = sh_util_strdup(_(sh_facilitynames[i].c_name)); break; }
281 ++i;
282 }
283 pri = LOG_PRI(priority);
284 i = 0;
285 while (sh_prioritynames[i].c_name != NULL)
286 {
287 if (sh_prioritynames[i].c_val == pri)
288 { cpri = sh_util_strdup(_(sh_prioritynames[i].c_name)); break; }
289 ++i;
290 }
291
292 /* here we do not expect an xml formatted message, thus we escape
293 xml special chars (flag == 1) */
294 tmp = sh_tools_safe_name (ptr, 1);
295 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_INET_SYSLOG,
296 namebuf,
297 (cfac == NULL) ? _("none") : cfac,
298 (cpri == NULL) ? _("none") : cpri,
299 (tmp == NULL) ? _("none") : tmp);
300 if (cfac != NULL)
301 SH_FREE(cfac);
302 if (cpri != NULL)
303 SH_FREE(cpri);
304 SH_FREE(tmp);
305 /* SH_FREE(bptr); */
306 }
307
308 else if (res < 0 && errno != EINTR)
309 {
310 res = errno;
311 TPT(( 0, FIL__, __LINE__, _("msg=<UDP error: %d>\n"), res));
312 sh_error_handle((-1), FIL__, __LINE__, res, MSG_ERR_SYSLOG,
313 sh_error_message(res, errbuf, sizeof(errbuf)),
314 namebuf);
315
316 /* don't accept anything the next 2 seconds
317 */
318 return_next = time(NULL);
319 SL_RETURN( (-1), _("sh_xfer_recv_syslog_socket"));
320 }
321 SL_RETURN( (0), _("sh_xfer_recv_syslog_socket"));
322}
323
324int set_syslog_active(const char * c)
325{
326 return sh_util_flagval(c, &enable_syslog_socket);
327}
328
329static int do_syslog_socket(int domain, int type, int protocol,
330 struct sockaddr * sa, int salen)
331{
332 int flag = 1; /* non-zero to enable an option */
333 int sock;
334 int errnum;
335 int res;
336
337 /* create the socket, bind() it and listen()
338 */
339 sock = socket(domain, type, protocol);
340
341 if (sock < 0)
342 {
343 errnum = errno;
344 sh_xfer_printerr (_("syslog socket"), errnum, 514, __LINE__);
345 return -1;
346 }
347 (void) retry_fcntl( FIL__, __LINE__, sock, F_SETFD, 1 );
348
349 if ( setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
350 (void *) &flag, sizeof(flag)) < 0 )
351 {
352 errnum = errno;
353 sh_xfer_printerr (_("syslog setsockopt SO_REUSEADDR"),
354 errnum, 514, __LINE__);
355 return -1;
356 }
357
358#if defined(SO_BSDCOMPAT)
359 if ( setsockopt(sock, SOL_SOCKET, SO_BSDCOMPAT,
360 (void *) &flag, sizeof(flag)) < 0 )
361 {
362 errnum = errno;
363 sh_xfer_printerr (_("syslog setsockopt SO_BSDCOMPAT"),
364 errnum, 514, __LINE__);
365 return -1;
366 }
367#endif
368
369 res = bind(sock, sa, salen);
370
371 if ( res < 0)
372 {
373 errnum = errno;
374 sh_xfer_printerr (_("syslog bind"), errnum, 514, __LINE__);
375 sl_close_fd(FIL__, __LINE__, sock);
376 return -1;
377 }
378 return sock;
379}
380
381/* callerFlag == S_TRUE means override the enable_syslog_socket flag
382 */
383int sh_xfer_create_syslog_socket (int callerFlag)
384{
385 int sock;
386
387#if defined(USE_IPVX)
388 struct addrinfo *ai;
389 struct addrinfo *p;
390 struct addrinfo hints;
391#else
392 struct sockaddr_in addr;
393 int addrlen = sizeof(addr);
394#endif
395
396 SL_ENTER(_("sh_xfer_create_syslog_socket"));
397
398 if (callerFlag == S_FALSE)
399 {
400 if (enable_syslog_socket == S_FALSE && sh_xfer_syslog_sock_n > 0)
401 {
402 /* user does not wish to use this facility
403 */
404 TPT(( 0, FIL__, __LINE__, _("msg=<close syslog socket>\n")));
405 for (sock = 0; sock < sh_xfer_syslog_sock_n; ++sock)
406 {
407 sl_close_fd(FIL__, __LINE__, sh_xfer_syslog_sock[sock]);
408 sh_xfer_syslog_sock[0] = -1;
409 }
410 }
411 SL_RETURN((-1), _("sh_xfer_create_syslog_socket"));
412 }
413
414 sh_xfer_printerr (NULL, 0, 514, __LINE__);
415
416#if !defined(USE_IPVX)
417
418 memset(&addr, 0, sizeof(addr));
419 addr.sin_family = AF_INET;
420 addr.sin_port = htons(514);
421
422 sock = do_syslog_socket(AF_INET, SOCK_DGRAM, 0,
423 (struct sockaddr *) &addr, addrlen);
424
425 if (sock >= 0) {
426 sh_xfer_syslog_sock[0] = sock;
427 sh_xfer_syslog_sock_n = 1;
428 }
429
430#else
431 memset (&hints, 0, sizeof (hints));
432 hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
433 hints.ai_socktype = SOCK_DGRAM;
434 if (getaddrinfo (NULL, "syslog", &hints, &ai) != 0)
435 {
436 int errnum = errno;
437 sh_xfer_printerr (_("getaddrinfo"), errnum, 514, __LINE__);
438 SL_RETURN((-1), _("sh_xfer_create_syslog_socket"));
439 }
440
441 p = ai;
442
443 while (p != NULL && sh_xfer_syslog_sock_n < SH_SOCKMAX)
444 {
445 sock = do_syslog_socket(p->ai_family, p->ai_socktype, p->ai_protocol,
446 p->ai_addr, p->ai_addrlen);
447
448 if (sock >= 0) {
449 if (sh_xfer_syslog_sock_n < SH_SOCKMAX) {
450 sh_xfer_syslog_sock[sh_xfer_syslog_sock_n] = sock;
451 ++sh_xfer_syslog_sock_n;
452 }
453 else {
454 sl_close_fd (FIL__, __LINE__, sock);
455 }
456 } else if (sock == -1) {
457 freeaddrinfo (ai);
458 goto end;
459 }
460 p = p->ai_next;
461 }
462 freeaddrinfo (ai);
463
464 end:
465#endif
466 if (sh_xfer_syslog_sock_n > 1)
467 SH_MINSOCK += (sh_xfer_syslog_sock_n - 1);
468
469 SL_RETURN((sh_xfer_syslog_sock_n), _("sh_xfer_create_syslog_socket"));
470}
471/* #ifdef INET_SYSLOG */
472#endif
473
474/* #ifdef SH_WITH_SERVER */
475#endif
Note: See TracBrowser for help on using the repository browser.