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