source: trunk/src/sh_err_console.c@ 321

Last change on this file since 321 was 252, checked in by katerina, 15 years ago

Add code to check for stale file records on close() and fclose(), fix sl_close() to handle open stream (ticket #163).

File size: 9.4 KB
Line 
1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 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
24#include "samhain.h"
25#include "sh_error.h"
26#include "sh_utils.h"
27
28#undef FIL__
29#define FIL__ _("sh_err_console.c")
30
31#include <stdio.h>
32#include <sys/types.h>
33#include <fcntl.h>
34#include <unistd.h>
35#include <signal.h>
36
37extern int OnlyStderr;
38
39
40#if !defined(O_NONBLOCK)
41#if defined(O_NDELAY)
42#define O_NONBLOCK O_NDELAY
43#else
44#define O_NONBLOCK 0
45#endif
46#endif
47
48#if defined(WITH_MESSAGE_QUEUE)
49
50#if defined(HAVE_SYS_MSG_H)
51
52#include <sys/ipc.h>
53#include <sys/msg.h>
54
55struct sh_msgbuf {
56 long mtype;
57 char mtext[1]; /* <-- sizeof(mtext) will be 1+MY_MAX_MSG */
58};
59
60static int msgq_enabled = S_FALSE;
61
62/* The identifier of the message queue
63 */
64static int msgid = -1;
65
66/* Open the SysV message queue, creating it when neccesary
67 */
68static int open_ipc(void)
69{
70 key_t key;
71 int error;
72#if defined(WITH_TPT)
73 char errbuf[SH_ERRBUF_SIZE];
74#endif
75
76 SL_ENTER(_("open_ipc"));
77
78 /* get key
79 */
80 key = ftok ("/tmp", '#');
81 if (key == (key_t) -1)
82 {
83 error = errno;
84 TPT(( 0, FIL__, __LINE__, _("msg=<ftok: %s> errno=<%d>\n"),
85 sh_error_message(error, errbuf, sizeof(errbuf)), error));
86 SL_RETURN(-1, _("open_ipc"));
87 }
88
89 /* get message identifier
90 */
91 msgid = msgget (key, IPC_CREAT|MESSAGE_QUEUE_MODE);
92
93 if (msgid < 0)
94 {
95 error = errno;
96 TPT(( 0, FIL__, __LINE__, _("msg=<msgget: %s> errno=<%d>\n"),
97 sh_error_message(error, errbuf, sizeof(errbuf)), error));
98 SL_RETURN(-1, _("open_ipc"));
99 }
100
101 SL_RETURN(0, _("open_ipc"));
102}
103
104/* Close the SysV message queue
105 */
106void close_ipc (void)
107{
108 SL_ENTER(_("close_ipc"));
109
110 if (msgid != (-1))
111 (void) msgctl (msgid, IPC_RMID, NULL);
112 SL_RET0(_("close_ipc"));
113}
114
115/* Enable the message queue
116 */
117int enable_msgq(const char * foo)
118{
119 int i;
120
121 SL_ENTER(_("enable_msgq"));
122 i = sh_util_flagval(foo, &msgq_enabled);
123 SL_RETURN(i, _("enable_msgq"));
124}
125
126/* #define MY_MAX_MSG 254 */
127#define MY_MAX_MSG 1022
128
129static int push_message_queue (const char * msg)
130{
131 struct sh_msgbuf* recv_msg = NULL;
132 int rc = -1;
133 static int status = -1;
134 int error;
135 int count = 0;
136#if defined(WITH_TPT)
137 char errbuf[SH_ERRBUF_SIZE];
138#endif
139
140 SL_ENTER(_("push_message_queue"));
141
142 if (msgq_enabled == -1)
143 {
144 TPT(( 0, FIL__, __LINE__, _("msg=<msg_queue not enabled>\n")));
145 SL_RETURN(0, _("push_message_queue"));
146 }
147
148 if (status < 0)
149 {
150 TPT(( 0, FIL__, __LINE__, _("msg=<msg_queue not open>\n")));
151 status = open_ipc();
152 }
153
154 if (status < 0)
155 {
156 TPT(( 0, FIL__, __LINE__, _("msg=<open_ipc() failed>\n")));
157 SL_RETURN(-1, _("push_message_queue"));
158 }
159
160 /* struct msgbuf {
161 * long mtype;
162 * char mtext[1]; <-- sizeof(mtext) will be 1+MY_MAX_MSG
163 * }
164 */
165 recv_msg = (struct sh_msgbuf*) SH_ALLOC(sizeof(struct sh_msgbuf)+MY_MAX_MSG);
166 recv_msg->mtype = 1;
167 sl_strlcpy (recv_msg->mtext, msg, MY_MAX_MSG+1);
168
169 count = 0;
170
171 send_it:
172
173 if (count > 1)
174 {
175 SH_FREE(recv_msg);
176 SL_RETURN(-1, _("push_message_queue"));
177 }
178
179 /* send the message
180 */
181 do {
182 errno = 0;
183 rc = msgsnd(msgid, recv_msg, strlen(recv_msg->mtext)+1, IPC_NOWAIT);
184 }
185 while (rc < 0 && errno == EINTR);
186
187 if (rc == -1 && errno != EAGAIN)
188 {
189 /* EIDRM is not in OpenBSD
190 */
191 if (errno == EINVAL
192#if defined(EIDRM)
193 || errno == EIDRM
194#endif
195 )
196 {
197 TPT(( 0, FIL__, __LINE__, _("msg=<msg_queue not open>\n")));
198 status = open_ipc();
199 if (status == 0)
200 {
201 ++count;
202 goto send_it;
203 }
204 }
205 else
206 {
207 error = errno;
208 TPT(( 0, FIL__, __LINE__, _("msg=<msgsnd: %s> errno=<%d>\n"),
209 sh_error_message(error, errbuf, sizeof(errbuf)), error));
210 SH_FREE(recv_msg);
211 SL_RETURN(-1, _("push_message_queue"));
212 }
213 }
214
215 SH_FREE(recv_msg);
216 SL_RETURN(0, _("push_message_queue"));
217}
218/* if defined(HAVE_SYS_MSG_H) */
219#else
220
221#error **********************************************
222#error
223#error The sys/msg.h header was not found,
224#error cannot compile with --enable-message-queue
225#error
226#error **********************************************
227
228#endif
229
230#endif
231
232static int count_dev_console = 0;
233
234void reset_count_dev_console(void)
235{
236 count_dev_console = 0;
237 return;
238}
239
240/* ---- Set the console device. ----
241 */
242int sh_log_set_console (const char * address)
243{
244 SL_ENTER(_("sh_log_set_console"));
245 if (address != NULL && count_dev_console < 2
246 && sl_strlen(address) < SH_PATHBUF)
247 {
248 if (count_dev_console == 0)
249 (void) sl_strlcpy (sh.srvcons.name, address, SH_PATHBUF);
250 else
251 (void) sl_strlcpy (sh.srvcons.alt, address, SH_PATHBUF);
252
253 ++count_dev_console;
254 SL_RETURN(0, _("sh_log_set_console"));
255 }
256 SL_RETURN((-1), _("sh_log_set_console"));
257}
258
259#if defined(WITH_TRACE) || defined(WITH_TPT)
260char * sh_log_console_name (void)
261{
262 if (! sh.srvcons.name || sh.srvcons.name[0] == '\0' ||
263 0 == strcmp(sh.srvcons.name, _("NULL")))
264 return (_("/dev/console"));
265 return sh.srvcons.name;
266}
267#endif
268
269#ifndef STDERR_FILENO
270#define STDERR_FILENO 2
271#endif
272
273/* ---- Print out a message. ----
274 */
275int sh_log_console (const /*@null@*/char *errmsg)
276{
277 static int service_failure[2] = { 0, 0};
278 int fd[2] = { -1, -1};
279 int sflags;
280 int cc;
281 size_t len;
282 int ccMax = 1;
283 int retval = -1;
284 /* static int logkey_seen = 0; */
285 int error;
286 struct sigaction sa_new, sa_old;
287 static int blockMe = 0;
288 int val_return;
289
290 SL_ENTER(_("sh_log_console"));
291
292 if (errmsg == NULL || blockMe == 1)
293 {
294 SL_RETURN(0, _("sh_log_console"));
295 }
296 else
297 blockMe = 1;
298
299
300#ifdef WITH_MESSAGE_QUEUE
301 if (0 != push_message_queue (errmsg))
302 {
303 TPT(( 0, FIL__, __LINE__, _("msg=<push_message_queue() failed>\n")));
304 }
305#endif
306
307 sa_new.sa_handler = SIG_IGN;
308 (void) sigemptyset(&sa_new.sa_mask);
309 sa_new.sa_flags = 0;
310
311 /* Ignore SIGPIPE in case the console is actually a pipe.
312 */
313 (void) retry_sigaction(FIL__, __LINE__, SIGPIPE, &sa_new, &sa_old);
314
315 if (sh.flag.isdaemon == S_FALSE || OnlyStderr == S_TRUE)
316 {
317 len = strlen(errmsg);
318 do {
319 val_return = write(STDERR_FILENO, errmsg, len);
320 } while (val_return < 0 && errno == EINTR);
321 do {
322 val_return = write(STDERR_FILENO, "\n", 1);
323 } while (val_return < 0 && errno == EINTR);
324 /*
325 * fprintf (stderr, "%s\n", errmsg);
326 */
327 (void) retry_sigaction(FIL__, __LINE__, SIGPIPE, &sa_old, NULL);
328 blockMe = 0;
329 SL_RETURN(0, _("sh_log_console"));
330 }
331
332 /* --- daemon && initialized ---
333 */
334 if ( (OnlyStderr == S_FALSE) )
335 {
336 fd[0] = open ( sh.srvcons.name, O_WRONLY|O_APPEND|O_NOCTTY|O_NONBLOCK);
337 if (fd[0] >= 0) {
338 sflags = (int) retry_fcntl(FIL__, __LINE__, fd[0], F_GETFL, 0);
339 if (sflags >= 0)
340 {
341 (void) retry_fcntl(FIL__, __LINE__, fd[0],
342 F_SETFL, sflags & ~O_NONBLOCK);
343 }
344 }
345
346 if (sh.srvcons.alt != NULL && sh.srvcons.alt[0] != '\0')
347 {
348 fd[1] = open (sh.srvcons.alt, O_WRONLY|O_APPEND|O_NOCTTY|O_NONBLOCK);
349 if (fd[1] >= 0) {
350 sflags = (int) retry_fcntl(FIL__, __LINE__, fd[1], F_GETFL, 0);
351 if (sflags >= 0)
352 {
353 (void) retry_fcntl(FIL__, __LINE__, fd[1],
354 F_SETFL, sflags & ~O_NONBLOCK);
355 }
356 ccMax = 2;
357 }
358 }
359
360 for (cc = 0; cc < ccMax; ++cc)
361 {
362
363 if (fd[cc] < 0 && service_failure[cc] == 0)
364 {
365 error = errno;
366 sh_error_handle ((-1), FIL__, __LINE__, error, MSG_SRV_FAIL,
367 _("console"),
368 (cc == 0) ? sh.srvcons.name : sh.srvcons.alt);
369 service_failure[cc] = 1;
370 }
371
372 if (fd[cc] >= 0)
373 {
374 do {
375 val_return = write(fd[cc], errmsg, strlen(errmsg));
376 } while (val_return < 0 && errno == EINTR);
377 do {
378 val_return = write(fd[cc], "\r\n", 2);
379 } while (val_return < 0 && errno == EINTR);
380 (void) sl_close_fd(FIL__, __LINE__, fd[cc]);
381 service_failure[cc] = 0;
382 }
383 }
384 }
385 else
386 retval = 0;
387
388 (void) retry_sigaction(FIL__, __LINE__, SIGPIPE, &sa_old, NULL);
389 blockMe = 0;
390 SL_RETURN(retval, _("sh_log_console"));
391}
392
393
Note: See TracBrowser for help on using the repository browser.