Imported Upstream version 2.4.3
[platform/upstream/audit.git] / audisp / plugins / remote / audisp-remote.c
1 /* audisp-remote.c --
2  * Copyright 2008-2012 Red Hat Inc., Durham, North Carolina.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * Authors:
20  *   Steve Grubb <sgrubb@redhat.com>
21  *
22  */
23
24 #include "config.h"
25 #include <stdio.h>
26 #include <signal.h>
27 #include <syslog.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <netdb.h>
31 #include <unistd.h>
32 #include <stdlib.h>
33 #include <errno.h>
34 #include <time.h>
35 #include <fcntl.h>
36 #include <sys/select.h>
37 #include <poll.h>
38 #include <sys/socket.h>
39 #include <sys/stat.h>
40 #include <sys/wait.h>
41 #include <netinet/in.h>
42 #include <netinet/tcp.h>
43 #ifdef USE_GSSAPI
44 #include <gssapi/gssapi.h>
45 #include <gssapi/gssapi_generic.h>
46 #include <krb5.h>
47 #endif
48 #ifdef HAVE_LIBCAP_NG
49 #include <cap-ng.h>
50 #endif
51 #include "libaudit.h"
52 #include "private.h"
53 #include "remote-config.h"
54 #include "queue.h"
55 #include "remote-fgets.h"
56
57 #define CONFIG_FILE "/etc/audisp/audisp-remote.conf"
58 #define BUF_SIZE 32
59
60 /* MAX_AUDIT_MESSAGE_LENGTH, aligned to 4 KB so that an average q_append() only
61    writes to two disk disk blocks (1 aligned data block, 1 header block). */
62 #define QUEUE_ENTRY_SIZE (3*4096)
63
64 /* Error types */
65 #define ET_SUCCESS       0
66 #define ET_PERMANENT    -1
67 #define ET_TEMPORARY    -2
68
69 /* Global Data */
70 static volatile int stop = 0;
71 static volatile int hup = 0;
72 static volatile int suspend = 0;
73 static volatile int dump = 0;
74 static volatile int transport_ok = 0;
75 static volatile int sock=-1;
76 static volatile int remote_ended = 0, quiet = 0;
77 static int ifd;
78 remote_conf_t config;
79
80 /* Constants */
81 static const char *SINGLE = "1";
82 static const char *HALT = "0";
83 static const char *INIT_PGM = "/sbin/init";
84 static const char *SPOOL_FILE = "/var/spool/audit/remote.log";
85
86 /* Local function declarations */
87 static int check_message(void);
88 static int relay_event(const char *s, size_t len);
89 static int init_transport(void);
90 static int stop_transport(void);
91 static int ar_read (int, void *, int);
92 static int ar_write (int, const void *, int);
93
94 #ifdef USE_GSSAPI
95 /* We only ever talk to one server, so we don't need per-connection
96    credentials.  These are the ones we talk to the server with.  */
97 gss_ctx_id_t my_context;
98
99 #define REQ_FLAGS GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG
100 #define USE_GSS (config.enable_krb5)
101 #endif
102
103 /* Compile-time expression verification */
104 #define verify(E) do {                          \
105                 char verify__[(E) ? 1 : -1];    \
106                 (void)verify__;                 \
107         } while (0)
108
109 /*
110  * SIGTERM handler
111  */
112 static void term_handler( int sig )
113 {
114         stop = 1;
115 }
116
117 /*
118  * SIGHUP handler: re-read config
119  */
120 static void hup_handler( int sig )
121 {
122         hup = 1;
123 }
124
125 static void reload_config(void)
126 {
127         stop_transport(); // FIXME: We should only stop transport if necessary
128         hup = 0;
129 }
130
131 /*
132  * SIGSUR1 handler: dump stats
133  */
134 static void user1_handler( int sig )
135 {
136         dump = 1;
137 }
138
139 static void dump_stats(struct queue *queue)
140 {
141         syslog(LOG_INFO, "suspend=%s, transport_ok=%s, queue_size=%zu",
142                 suspend ? "yes" : "no",
143                 transport_ok ? "yes" : "no",
144                 q_queue_length(queue));
145         dump = 0;
146 }
147
148 /*
149  * SIGSUR2 handler: resume logging
150  */
151 static void user2_handler( int sig )
152 {
153         suspend = 0;
154 }
155
156 /*
157  * SIGCHLD handler: reap exiting processes
158  */
159 static void child_handler(int sig)
160 {
161         while (waitpid(-1, NULL, WNOHANG) > 0)
162                 ; /* empty */
163 }
164
165 /*
166  * Handlers for various events coming back from the remote server.
167  * Return -1 if the remote dispatcher should exit.
168  */
169
170 /* Loss of sync - got an invalid response.  */
171 static int sync_error_handler (const char *why)
172 {
173         /* "why" has human-readable details on why we've lost (or will
174            be losing) sync.  Sync errors are transient - if a retry
175            doesn't fix it, we eventually call network_failure_handler
176            which has all the user-tweakable actions.  */
177         syslog (LOG_ERR, "lost/losing sync, %s", why);
178         return 0;
179 }
180
181 static void change_runlevel(const char *level)
182 {
183         char *argv[3];
184         int pid;
185
186         pid = fork();
187         if (pid < 0) {
188                 syslog(LOG_ALERT, 
189                        "audisp-remote failed to fork switching runlevels");
190                 return;
191         }
192         if (pid)        /* Parent */
193                 return;
194
195         /* Child */
196         argv[0] = (char *)INIT_PGM;
197         argv[1] = (char *)level;
198         argv[2] = NULL;
199         execve(INIT_PGM, argv, NULL);
200         syslog(LOG_ALERT, "audisp-remote failed to exec %s", INIT_PGM);
201         exit(1);
202 }
203
204 static void safe_exec(const char *exe, const char *message)
205 {
206         char *argv[3];
207         int pid;
208
209         if (exe == NULL) {
210                 syslog(LOG_ALERT,  
211                         "Safe_exec passed NULL for program to execute");
212                 return;
213         }
214
215         pid = fork();
216         if (pid < 0) {
217                 syslog(LOG_ALERT,
218                         "audisp-remote failed to fork doing safe_exec");
219                 return;
220         }
221         if (pid)        /* Parent */
222                 return;
223
224         /* Child */
225         argv[0] = (char *)exe;
226         argv[1] = (char *)message;
227         argv[2] = NULL;
228         execve(exe, argv, NULL);
229         syslog(LOG_ALERT, "audisp-remote failed to exec %s", exe);
230         exit(1);
231 }
232
233 static int do_action (const char *desc, const char *message,
234                        int log_level,
235                        failure_action_t action, const char *exe)
236 {
237         switch (action)
238         {
239         case FA_IGNORE:
240                 return 0;
241         case FA_SYSLOG:
242                 syslog (log_level, "%s, %s", desc, message);
243                 return 0;
244         case FA_EXEC:
245                 safe_exec (exe, message);
246                 return 0;
247         case FA_SUSPEND:
248                 syslog (log_level,
249                         "suspending remote logging due to %s", desc);
250                 suspend = 1;
251                 return 0;
252         case FA_RECONNECT:
253                 syslog (log_level,
254         "remote logging disconnected due to %s, will attempt reconnection",
255                         desc);
256                 return 0;
257         case FA_SINGLE:
258                 syslog (log_level,
259         "remote logging is switching system to single user mode due to %s",
260                         desc);
261                 change_runlevel(SINGLE);
262                 return -1;
263         case FA_HALT:
264                 syslog (log_level,
265                         "remote logging halting system due to %s", desc);
266                 change_runlevel(HALT);
267                 return -1;
268         case FA_STOP:
269                 syslog (log_level, "remote logging stopping due to %s, %s",
270                         desc, message);
271                 stop = 1;
272                 return -1;
273         }
274         syslog (log_level, "unhandled action %d for %s", action, desc);
275         return -1;
276 }
277
278 static int network_failure_handler (const char *message)
279 {
280         return do_action ("network failure", message,
281                           LOG_WARNING,
282                           config.network_failure_action,
283                           config.network_failure_exe);
284 }
285
286 static int remote_disk_low_handler (const char *message)
287 {
288         return do_action ("remote server is low on disk space", message,
289                           LOG_WARNING,
290                           config.disk_low_action, config.disk_low_exe);
291 }
292
293 static int remote_disk_full_handler (const char *message)
294 {
295         return do_action ("remote server's disk is full", message,
296                           LOG_ERR,
297                           config.disk_full_action, config.disk_full_exe);
298 }
299
300 static int remote_disk_error_handler (const char *message)
301 {
302         return do_action ("remote server has a disk error", message,
303                           LOG_ERR,
304                           config.disk_error_action, config.disk_error_exe);
305 }
306
307 static int remote_server_ending_handler (const char *message)
308 {
309         stop_transport();
310         remote_ended = 1;
311         return do_action ("remote server is going down", message,
312                           LOG_NOTICE,
313                           config.remote_ending_action,
314                           config.remote_ending_exe);
315 }
316
317 static int generic_remote_error_handler (const char *message)
318 {
319         return do_action ("unrecognized remote error", message,
320                           LOG_ERR, config.generic_error_action,
321                           config.generic_error_exe);
322 }
323
324 static int generic_remote_warning_handler (const char *message)
325 {
326         return do_action ("unrecognized remote warning", message,
327                           LOG_WARNING,
328                           config.generic_warning_action,
329                           config.generic_warning_exe);
330 }
331
332 /* Report and handle a queue error, using errno. */
333 static void queue_error(void)
334 {
335         char *errno_str;
336
337         errno_str = strerror(errno);
338         do_action("queue error", errno_str, LOG_ERR, config.queue_error_action,
339                   config.queue_error_exe);
340 }
341
342 static void send_heartbeat (void)
343 {
344         relay_event (NULL, 0);
345 }
346
347 static void do_overflow_action(void)
348 {
349         switch (config.overflow_action)
350         {
351                 case OA_IGNORE:
352                         break;
353                 case OA_SYSLOG:
354                         syslog(LOG_ERR, "queue is full - dropping event");
355                         break;
356                 case OA_SUSPEND:
357                         syslog(LOG_ALERT,
358                             "Audisp-remote is suspending event processing due to overflowing its queue.");
359                         suspend = 1;
360                         break;
361                 case OA_SINGLE:
362                         syslog(LOG_ALERT,
363                                 "Audisp-remote is now changing the system to single user mode due to overflowing its queue");
364                         change_runlevel(SINGLE);
365                         break;
366                 case OA_HALT:
367                         syslog(LOG_ALERT,
368                                 "Audisp-remote is now halting the system due to overflowing its queue");
369                         change_runlevel(HALT);
370                         break;
371                 default:
372                         syslog(LOG_ALERT, "Unknown overflow action requested");
373                         break;
374         }
375 }
376
377 /* Initialize and return a queue depending on user's configuration.
378    On error return NULL and set errno. */
379 static struct queue *init_queue(void)
380 {
381         const char *path;
382         int q_flags;
383
384         if (config.queue_file != NULL)
385                 path = config.queue_file;
386         else
387                 path = SPOOL_FILE;
388         q_flags = Q_IN_MEMORY;
389         if (config.mode == M_STORE_AND_FORWARD)
390                 /* FIXME: let user control Q_SYNC? */
391                 q_flags |= Q_IN_FILE | Q_CREAT | Q_RESIZE;
392         verify(QUEUE_ENTRY_SIZE >= MAX_AUDIT_MESSAGE_LENGTH);
393         return q_open(q_flags, path, config.queue_depth, QUEUE_ENTRY_SIZE);
394 }
395
396 /* Send a record from QUEUE to the remote system */
397 static void send_one(struct queue *queue)
398 {
399         char event[MAX_AUDIT_MESSAGE_LENGTH];
400         int len;
401
402         if (suspend || !transport_ok)
403                 return;
404
405         len = q_peek(queue, event, sizeof(event));
406         if (len == 0)
407                 return;
408         if (len < 0) {
409                 queue_error();
410                 return;
411         }
412
413         /* We send len -1 to remove trailing \n */
414         if (relay_event(event, len-1) < 0)
415                 return;
416
417         if (q_drop_head(queue) != 0)
418                 queue_error();
419 }
420
421 int main(int argc, char *argv[])
422 {
423         struct sigaction sa;
424         struct queue *queue;
425         int rc;
426         size_t q_len;
427
428         /* Register sighandlers */
429         sa.sa_flags = 0;
430         sigemptyset(&sa.sa_mask);
431         /* Set handler for the ones we care about */
432         sa.sa_handler = term_handler;
433         sigaction(SIGTERM, &sa, NULL);
434         sa.sa_handler = hup_handler;
435         sigaction(SIGHUP, &sa, NULL);
436         sa.sa_handler = user1_handler;
437         sigaction(SIGUSR1, &sa, NULL);
438         sa.sa_handler = user2_handler;
439         sigaction(SIGUSR2, &sa, NULL);
440         sa.sa_handler = child_handler;
441         sigaction(SIGCHLD, &sa, NULL);
442         if (load_config(&config, CONFIG_FILE))
443                 return 6;
444
445         // ifd = open("test.log", O_RDONLY);
446         ifd = 0;
447         fcntl(ifd, F_SETFL, O_NONBLOCK);
448
449         /* We fail here if the transport can't be initialized because of some
450          * permanent (i.e. operator) problem, such as misspelled host name. */
451         rc = init_transport();
452         if (rc == ET_PERMANENT)
453                 return 1;
454         queue = init_queue();
455         if (queue == NULL) {
456                 syslog(LOG_ERR, "Error initializing audit record queue: %m");
457                 return 1;
458         }
459
460 #ifdef HAVE_LIBCAP_NG
461         // Drop capabilities
462         capng_clear(CAPNG_SELECT_BOTH);
463         if (config.local_port && config.local_port < 1024)
464                 capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
465                         CAP_NET_BIND_SERVICE);
466         capng_apply(CAPNG_SELECT_BOTH);
467 #endif
468         syslog(LOG_NOTICE, "Audisp-remote started with queue_size: %zu",
469                 q_queue_length(queue));
470
471         while (stop == 0) { //FIXME break out when socket is closed
472                 fd_set rfd, wfd;
473                 struct timeval tv;
474                 char event[MAX_AUDIT_MESSAGE_LENGTH];
475                 int n, fds = ifd + 1;
476
477                 /* Load configuration */
478                 if (hup) 
479                         reload_config();
480
481                 if (dump)
482                         dump_stats(queue);
483
484                 /* Setup select flags */
485                 FD_ZERO(&rfd);
486                 FD_SET(ifd, &rfd);      // input fd
487                 FD_ZERO(&wfd);
488                 if (sock > 0) {
489                         // Setup socket to read acks from server
490                         FD_SET(sock, &rfd); // remote socket
491                         if (sock > ifd)
492                                 fds = sock + 1;
493                         // If we have anything in the queue,
494                         // find out if we can send it
495                         if (q_queue_length(queue) && !suspend && transport_ok)
496                                 FD_SET(sock, &wfd);
497                 }
498
499                 if (config.heartbeat_timeout > 0) {
500                         tv.tv_sec = config.heartbeat_timeout;
501                         tv.tv_usec = 0;
502                         n = select(fds, &rfd, &wfd, NULL, &tv);
503                 } else
504                         n = select(fds, &rfd, &wfd, NULL, NULL);
505                 if (n < 0)
506                         continue; // If here, we had some kind of problem
507
508                 if ((config.heartbeat_timeout > 0) && n == 0 && !remote_ended) {
509                         /* We attempt a hearbeat if select fails, which
510                          * may give us more heartbeats than we need. This
511                          * is safer than too few heartbeats.  */
512                         quiet = 1;
513                         send_heartbeat();
514                         quiet = 0;
515                         continue;
516                 }
517
518                 // See if we got a shutdown message from the server
519                 if (sock > 0 && FD_ISSET(sock, &rfd))
520                         check_message();
521
522                 // If we broke out due to one of these, cycle to start
523                 if (hup != 0 || stop != 0)
524                         continue;
525
526                 // See if input fd is also set
527                 if (FD_ISSET(ifd, &rfd)) {
528                         do {
529                                 if (remote_fgets(event, sizeof(event), ifd)) {
530                                         if (!transport_ok && remote_ended && 
531                                                 config.remote_ending_action ==
532                                                                  FA_RECONNECT) {
533                                                 quiet = 1;
534                                                 if (init_transport() ==
535                                                                 ET_SUCCESS)
536                                                         remote_ended = 0;
537                                                 quiet = 0;
538                                         }
539                                         /* Strip out EOE records */
540                                         if (*event == 't') {
541                                                 if (strncmp(event,
542                                                         "type=EOE", 8) == 0)
543                                                         continue;
544                                         } else {
545                                                 char *ptr = strchr(event, ' ');
546                                                 if (ptr) {
547                                                         ptr++;
548                                                         if (strncmp(ptr,
549                                                                 "type=EOE",
550                                                                         8) == 0)
551                                                                 continue;
552                                                 } else
553                                                         continue; //malformed
554                                         }
555                                         if (q_append(queue, event) != 0) {
556                                                 if (errno == ENOSPC)
557                                                         do_overflow_action();
558                                                 else
559                                                         queue_error();
560                                         }
561                                 } else if (remote_fgets_eof())
562                                         stop = 1;
563                         } while (remote_fgets_more(sizeof(event)));
564                 }
565                 // See if output fd is also set
566                 if (sock > 0 && FD_ISSET(sock, &wfd)) {
567                         // If so, try to drain backlog
568                         while (q_queue_length(queue) && !suspend &&
569                                         !stop && transport_ok)
570                                 send_one(queue);
571                 }
572         }
573         if (sock >= 0) {
574                 shutdown(sock, SHUT_RDWR);
575                 close(sock);
576         }
577         free_config(&config);
578         q_len = q_queue_length(queue);
579         q_close(queue);
580         if (stop)
581                 syslog(LOG_NOTICE, "audisp-remote is exiting on stop request, queue_size: %zu", q_len);
582
583         return q_len ? 1 : 0;
584 }
585
586 #ifdef USE_GSSAPI
587
588 /* Communications under GSS is done by token exchanges. Each "token" may
589    contain a message, perhaps signed, perhaps encrypted. The messages within
590    are what we're interested in, but the network sees the tokens. The
591    protocol we use for transferring tokens is to send the length first,
592    four bytes MSB first, then the token data. We return nonzero on error. */
593 static int recv_token(int s, gss_buffer_t tok)
594 {
595         int ret;
596         unsigned char lenbuf[4];
597         unsigned int len;
598
599         ret = ar_read(s, (char *) lenbuf, 4);
600         if (ret < 0) {
601                 syslog(LOG_ERR, "GSS-API error reading token length");
602                 return -1;
603         } else if (!ret) {
604                 return 0;
605         } else if (ret != 4) {
606                 syslog(LOG_ERR, "GSS-API error reading token length");
607                 return -1;
608         }
609
610         len = (   ((uint32_t)(lenbuf[0] & 0xFF) << 24)
611                 | ((uint32_t)(lenbuf[1] & 0xFF) << 16)
612                 | ((uint32_t)(lenbuf[2] & 0xFF) << 8)
613                 |  (uint32_t)(lenbuf[3] & 0xFF));
614
615         if (len > MAX_AUDIT_MESSAGE_LENGTH) {
616                 syslog(LOG_ERR,
617                         "GSS-API error: event length excedes MAX_AUDIT_LENGTH");
618                 return -1;
619         }
620         tok->length = len;
621         tok->value = (char *) malloc(tok->length ? tok->length : 1);
622         if (tok->length && tok->value == NULL) {
623                 syslog(LOG_ERR, "Out of memory allocating token data %zd %zx",
624                                 tok->length, tok->length);
625                 return -1;
626         }
627
628         ret = ar_read(s, (char *) tok->value, tok->length);
629         if (ret < 0) {
630                 syslog(LOG_ERR, "GSS-API error reading token data");
631                 free(tok->value);
632                 return -1;
633         } else if (ret != (int) tok->length) {
634                 syslog(LOG_ERR, "GSS-API error reading token data");
635                 free(tok->value);
636                 return -1;
637         }
638
639         return 0;
640 }
641
642 /* Same here.  */
643 int send_token(int s, gss_buffer_t tok)
644 {
645         int ret;
646         unsigned char lenbuf[4];
647         unsigned int len;
648
649         if (tok->length > 0xffffffffUL)
650                 return -1;
651
652         len = tok->length;
653         lenbuf[0] = (len >> 24) & 0xff;
654         lenbuf[1] = (len >> 16) & 0xff;
655         lenbuf[2] = (len >> 8) & 0xff;
656         lenbuf[3] = len & 0xff;
657
658         ret = ar_write(s, (char *) lenbuf, 4);
659         if (ret < 0) {
660                 syslog(LOG_ERR, "GSS-API error sending token length");
661                 return -1;
662         } else if (ret != 4) {
663                 syslog(LOG_ERR, "GSS-API error sending token length");
664                 return -1;
665         }
666
667         ret = ar_write(s, tok->value, tok->length);
668         if (ret < 0) {
669                 syslog(LOG_ERR, "GSS-API error sending token data");
670                 return -1;
671         } else if (ret != (int) tok->length) {
672                 syslog(LOG_ERR, "GSS-API error sending token data");
673                 return -1;
674         }
675
676         return 0;
677 }
678
679 static void gss_failure_2 (const char *msg, int status, int type)
680 {
681         OM_uint32 message_context = 0;
682         OM_uint32 min_status = 0;
683         gss_buffer_desc status_string;
684
685         do {
686                 gss_display_status (&min_status,
687                                     status,
688                                     type,
689                                     GSS_C_NO_OID,
690                                     &message_context,
691                                     &status_string);
692
693                 syslog (LOG_ERR, "GSS error: %s: %s",
694                         msg, (char *)status_string.value);
695
696                 gss_release_buffer(&min_status, &status_string);
697         } while (message_context != 0);
698 }
699
700 static void gss_failure (const char *msg, int major_status, int minor_status)
701 {
702         gss_failure_2 (msg, major_status, GSS_C_GSS_CODE);
703         if (minor_status)
704                 gss_failure_2 (msg, minor_status, GSS_C_MECH_CODE);
705 }
706
707 #define KCHECK(x,f) if (x) { \
708                 syslog (LOG_ERR, "krb5 error: %s in %s\n", krb5_get_error_message (kcontext, x), f); \
709                 return -1; }
710
711 #define KEYTAB_NAME "/etc/audisp/audisp-remote.key"
712 #define CCACHE_NAME "MEMORY:audisp-remote"
713
714 /* Each time we connect to the server, we negotiate a set of credentials and
715    a security context. To do this, we need our own credentials first. For
716    other Kerberos applications, the user will have called kinit (or otherwise
717    authenticated) first, but we don't have that luxury. So, we implement part
718    of kinit here. When our tickets expire, the usual close/open/retry logic
719    has us calling here again, where we re-init and get new tickets. */
720 static int negotiate_credentials (void)
721 {
722         gss_buffer_desc empty_token_buf = { 0, (void *) "" };
723         gss_buffer_t empty_token = &empty_token_buf;
724         gss_buffer_desc send_tok, recv_tok, *token_ptr;
725         gss_ctx_id_t *gss_context = &my_context;
726         gss_buffer_desc name_buf;
727         gss_name_t service_name_e;
728         OM_uint32 major_status, minor_status, init_sec_min_stat;
729         OM_uint32 ret_flags;
730
731         /* Getting an initial ticket is outside the scope of GSS, so
732            we use Kerberos calls here.  */
733
734         int krberr;
735         krb5_context kcontext = NULL;
736         char *realm_name;
737         krb5_principal audit_princ;
738         krb5_ccache ccache = NULL;
739         krb5_creds my_creds;
740         krb5_get_init_creds_opt options;
741         krb5_keytab keytab = NULL;
742         const char *krb5_client_name;
743         char *slashptr;
744         char host_name[255];
745         struct stat st;
746         const char *key_file;
747
748         token_ptr = GSS_C_NO_BUFFER;
749         *gss_context = GSS_C_NO_CONTEXT;
750         recv_tok.value = NULL;
751
752         krberr = krb5_init_context (&kcontext);
753         KCHECK (krberr, "krb5_init_context");
754
755         if (config.krb5_key_file)
756                 key_file = config.krb5_key_file;
757         else
758                 key_file = KEYTAB_NAME;
759         unsetenv ("KRB5_KTNAME");
760         setenv ("KRB5_KTNAME", key_file, 1);
761
762         if (stat (key_file, &st) == 0) {
763                 if ((st.st_mode & 07777) != 0400) {
764                         if (!quiet)
765                                 syslog (LOG_ERR,
766                         "%s is not mode 0400 (it's %#o) - compromised key?",
767                                         key_file, st.st_mode & 07777);
768                         return -1;
769                 }
770                 if (st.st_uid != 0) {
771                         if (!quiet)
772                                 syslog (LOG_ERR,
773                         "%s is not owned by root (it's %d) - compromised key?",
774                                         key_file, st.st_uid);
775                         return -1;
776                 }
777         }
778
779         /* This looks up the default real (*our* realm) from
780            /etc/krb5.conf (or wherever)  */
781         krberr = krb5_get_default_realm (kcontext, &realm_name);
782         KCHECK (krberr, "krb5_get_default_realm");
783
784         krb5_client_name = config.krb5_client_name ?
785                                 config.krb5_client_name : "auditd";
786         if (gethostname(host_name, sizeof(host_name)) != 0) {
787                 if (!quiet)
788                         syslog (LOG_ERR,
789                         "gethostname: host name longer than %ld characters?",
790                                 sizeof (host_name));
791                 return -1;
792         }
793
794         syslog (LOG_ERR, "kerberos principal: %s/%s@%s\n",
795                 krb5_client_name, host_name, realm_name);
796         /* Encode our own "name" as auditd/remote@EXAMPLE.COM.  */
797         krberr = krb5_build_principal (kcontext, &audit_princ,
798                                        strlen(realm_name), realm_name,
799                                        krb5_client_name, host_name, NULL);
800         KCHECK (krberr, "krb5_build_principal");
801
802         /* Locate our machine's key table, where our private key is
803          * held.  */
804         krberr = krb5_kt_resolve (kcontext, key_file, &keytab);
805         KCHECK (krberr, "krb5_kt_resolve");
806
807         /* Identify a cache to hold the key in.  The GSS wrappers look
808            up our credentials here.  */
809         krberr = krb5_cc_resolve (kcontext, CCACHE_NAME, &ccache);
810         KCHECK (krberr, "krb5_cc_resolve");
811
812         setenv("KRB5CCNAME", CCACHE_NAME, 1);
813
814         memset(&my_creds, 0, sizeof(my_creds));
815         memset(&options, 0, sizeof(options));
816         krb5_get_init_creds_opt_set_address_list(&options, NULL);
817         krb5_get_init_creds_opt_set_forwardable(&options, 0);
818         krb5_get_init_creds_opt_set_proxiable(&options, 0);
819         krb5_get_init_creds_opt_set_tkt_life(&options, 24*60*60);
820
821         /* Load our credentials from the key table.  */
822         krberr = krb5_get_init_creds_keytab(kcontext, &my_creds, audit_princ,
823                                             keytab, 0, NULL,
824                                             &options);
825         KCHECK (krberr, "krb5_get_init_creds_keytab");
826
827         /* Create the cache... */
828         krberr = krb5_cc_initialize(kcontext, ccache, audit_princ);
829         KCHECK (krberr, "krb5_cc_initialize");
830
831         /* ...and store our credentials in it.  */
832         krberr = krb5_cc_store_cred(kcontext, ccache, &my_creds);
833         KCHECK (krberr, "krb5_cc_store_cred");
834
835         /* The GSS code now has a set of credentials for this program.
836            I.e.  we know who "we" are.  Now we talk to the server to
837            get its credentials and set up a security context for encryption. */
838         if (config.krb5_principal == NULL) {
839                 const char *name = config.krb5_client_name ?
840                                         config.krb5_client_name : "auditd";
841                 config.krb5_principal = (char *) malloc (strlen (name) + 1
842                                         + strlen (config.remote_server) + 1);
843                 sprintf((char *)config.krb5_principal, "%s@%s",
844                         name, config.remote_server);
845         }
846         slashptr = strchr (config.krb5_principal, '/');
847         if (slashptr)
848                 *slashptr = '@';
849
850         name_buf.value = (char *)config.krb5_principal;
851         name_buf.length = strlen(name_buf.value) + 1;
852         major_status = gss_import_name(&minor_status, &name_buf,
853                                (gss_OID) gss_nt_service_name, &service_name_e);
854         if (major_status != GSS_S_COMPLETE) {
855                 gss_failure("importing name", major_status, minor_status);
856                 return -1;
857         }
858
859         /* Someone has to go first.  In this case, it's us.  */
860         if (send_token(sock, empty_token) < 0) {
861                 (void) gss_release_name(&minor_status, &service_name_e);
862                 return -1;
863         }
864
865         /* The server starts this loop with the token we just sent
866            (the empty one).  We start this loop with "no token".  */
867         token_ptr = GSS_C_NO_BUFFER;
868         *gss_context = GSS_C_NO_CONTEXT;
869
870         do {
871                 /* Give GSS a chance to digest what we have so far.  */
872                 major_status = gss_init_sec_context(&init_sec_min_stat,
873                         GSS_C_NO_CREDENTIAL, gss_context,
874                         service_name_e, NULL, REQ_FLAGS, 0,
875                         NULL,                   /* no channel bindings */
876                         token_ptr, NULL,        /* ignore mech type */
877                         &send_tok, &ret_flags, NULL);   /* ignore time_rec */
878
879                 if (token_ptr != GSS_C_NO_BUFFER)
880                         free(recv_tok.value);
881
882                 /* Send the server any tokens requested of us.  */
883                 if (send_tok.length != 0) {
884                         if (send_token(sock, &send_tok) < 0) {
885                                 (void) gss_release_buffer(&minor_status,
886                                                 &send_tok);
887                                 (void) gss_release_name(&minor_status,
888                                                 &service_name_e);
889                                 return -1;
890                         }
891                 }
892                 (void) gss_release_buffer(&minor_status, &send_tok);
893
894                 if (major_status != GSS_S_COMPLETE
895                     && major_status != GSS_S_CONTINUE_NEEDED) {
896                         gss_failure("initializing context", major_status,
897                                     init_sec_min_stat);
898                         (void) gss_release_name(&minor_status, &service_name_e);
899                         if (*gss_context != GSS_C_NO_CONTEXT)
900                                 gss_delete_sec_context(&minor_status,
901                                                 gss_context, GSS_C_NO_BUFFER);
902                         return -1;
903                 }
904
905                 /* Now get any tokens the sever sends back.  We use
906                    these back at the top of the loop.  */
907                 if (major_status == GSS_S_CONTINUE_NEEDED) {
908                         if (recv_token(sock, &recv_tok) < 0) {
909                                 (void) gss_release_name(&minor_status,
910                                                         &service_name_e);
911                                 return -1;
912                         }
913                         token_ptr = &recv_tok;
914                 }
915         } while (major_status == GSS_S_CONTINUE_NEEDED);
916
917         (void) gss_release_name(&minor_status, &service_name_e);
918
919 #if 0
920         major_status = gss_inquire_context (&minor_status, &my_context, NULL,
921                                             &service_name_e, NULL, NULL,
922                                             NULL, NULL, NULL);
923         if (major_status != GSS_S_COMPLETE) {
924                 gss_failure("inquiring target name", major_status, minor_status);
925                 return -1;
926         }
927         major_status = gss_display_name(&minor_status, service_name_e,
928                                         &recv_tok, NULL);
929         gss_release_name(&minor_status, &service_name_e);
930         if (major_status != GSS_S_COMPLETE) {
931                 gss_failure("displaying name", major_status, minor_status);
932                 return -1;
933         }
934         syslog(LOG_INFO, "GSS-API Connected to: %s",
935                   (char *)recv_tok.value);
936 #endif
937         return 0;
938 }
939 #endif
940
941 static int stop_sock(void)
942 {
943         if (sock >= 0) {
944                 shutdown(sock, SHUT_RDWR);
945                 close(sock);
946         }
947         sock = -1;
948         transport_ok = 0;
949
950         return 0;
951 }
952
953 static int stop_transport(void)
954 {
955         int rc;
956
957         switch (config.transport)
958         {
959                 case T_TCP:
960                         rc = stop_sock();
961                         break;
962                 default:
963                         rc = -1;
964                         break;
965         }
966         return rc;
967 }
968
969 static int init_sock(void)
970 {
971         int rc;
972         struct addrinfo *ai;
973         struct addrinfo hints;
974         char remote[BUF_SIZE];
975         int one=1;
976
977         if (sock >= 0) {
978                 syslog(LOG_NOTICE, "socket already setup");
979                 transport_ok = 1;
980                 return ET_SUCCESS;
981         }
982         memset(&hints, '\0', sizeof(hints));
983         hints.ai_flags = AI_ADDRCONFIG|AI_NUMERICSERV;
984         hints.ai_socktype = SOCK_STREAM;
985         snprintf(remote, BUF_SIZE, "%u", config.port);
986         rc = getaddrinfo(config.remote_server, remote, &hints, &ai);
987         if (rc) {
988                 if (!quiet)
989                         syslog(LOG_ERR,
990                                 "Error looking up remote host: %s - exiting",
991                                 gai_strerror(rc));
992                 if (rc == EAI_NONAME || rc == EAI_NODATA)
993                         return ET_PERMANENT;
994                 else
995                         return ET_TEMPORARY;
996         }
997         sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
998         if (sock < 0) {
999                 if (!quiet)
1000                         syslog(LOG_ERR, "Error creating socket: %s",
1001                         strerror(errno));
1002                 freeaddrinfo(ai);
1003                 return ET_TEMPORARY;
1004         }
1005
1006         setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof (int));
1007
1008         if (config.local_port != 0) {
1009                 struct sockaddr_in address;
1010                 
1011                 memset (&address, 0, sizeof(address));
1012                 address.sin_family = AF_INET;
1013                 address.sin_port = htons(config.local_port);
1014                 address.sin_addr.s_addr = htonl(INADDR_ANY);
1015
1016                 if (bind(sock, (struct sockaddr *)&address, sizeof(address))) {
1017                         if (!quiet)
1018                                 syslog(LOG_ERR,
1019                                "Cannot bind local socket to port %d",
1020                                         config.local_port);
1021                         stop_sock();
1022                         return ET_TEMPORARY;
1023                 }
1024
1025         }
1026         if (connect(sock, ai->ai_addr, ai->ai_addrlen)) {
1027                 if (!quiet)
1028                         syslog(LOG_ERR, "Error connecting to %s: %s",
1029                                 config.remote_server, strerror(errno));
1030                 freeaddrinfo(ai);
1031                 stop_sock();
1032                 return ET_TEMPORARY;
1033         }
1034
1035         freeaddrinfo(ai);
1036         setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&one, sizeof (int));
1037
1038         /* The idea here is to minimize the time between the message
1039            and the ACK, assuming that individual messages are
1040            infrequent enough that we can ignore the inefficiency of
1041            sending the header and message in separate packets.  */
1042         if (config.format == F_MANAGED)
1043                 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
1044                                 (char *)&one, sizeof (int));
1045
1046 #ifdef USE_GSSAPI
1047         if (USE_GSS) {
1048                 if (negotiate_credentials ())
1049                         return ET_PERMANENT;
1050         }
1051 #endif
1052
1053         transport_ok = 1;
1054         syslog(LOG_NOTICE, "Connected to %s", config.remote_server);
1055         return ET_SUCCESS;
1056 }
1057
1058 static int init_transport(void)
1059 {
1060         int rc;
1061
1062         switch (config.transport)
1063         {
1064                 case T_TCP:
1065                         rc = init_sock();
1066                         // We set this so that it will retry the connection
1067                         if (rc == ET_TEMPORARY)
1068                                 remote_ended = 1;
1069                         break;
1070                 default:
1071                         rc = ET_PERMANENT;
1072                         break;
1073         }
1074         return rc;
1075 }
1076
1077 static int ar_write (int sk, const void *buf, int len)
1078 {
1079         int rc = 0, r;
1080         while (len > 0) {
1081                 do {
1082                         r = write(sk, buf, len);
1083                 } while (r < 0 && errno == EINTR);
1084                 if (r < 0) {
1085                         if (errno == EPIPE)
1086                                 stop_sock();
1087                         return r;
1088                 }
1089                 if (r == 0)
1090                         break;
1091                 rc += r;
1092                 buf = (void *)((char *)buf + r);
1093                 len -= r;
1094         }
1095         return rc;
1096 }
1097
1098 static int ar_read (int sk, void *buf, int len)
1099 {
1100         int rc = 0, r, timeout = config.max_time_per_record * 1000;
1101         struct pollfd pfd;
1102
1103         pfd.fd=sk;
1104         pfd.events=POLLIN | POLLPRI | POLLHUP | POLLERR | POLLNVAL;
1105         while (len > 0) {
1106                 do {
1107                         // reads can hang if cable is disconnected
1108                         int prc = poll(&pfd, (nfds_t) 1, timeout);
1109                         if (prc <= 0)
1110                                 return -1;
1111                         r = read(sk, buf, len);
1112                 } while (r < 0 && errno == EINTR);
1113                 if (r < 0) {
1114                         if (errno == EPIPE)
1115                                 stop_sock();
1116                         return r;
1117                 }
1118                 if (r == 0)
1119                         break;
1120                 rc += r;
1121                 buf = (void *)((char *)buf + r);
1122                 len -= r;
1123         }
1124         return rc;
1125 }
1126
1127 static int relay_sock_ascii(const char *s, size_t len)
1128 {
1129         int rc;
1130
1131         if (len == 0)
1132                 return 0;
1133
1134         if (!transport_ok) {
1135                 if (init_transport ())
1136                         return -1;
1137         }
1138
1139         rc = ar_write(sock, s, len);
1140         if (rc <= 0) {
1141                 stop = 1;
1142                 syslog(LOG_ERR,"Connection to %s closed unexpectedly - exiting",
1143                        config.remote_server);
1144                 return -1;
1145         }
1146
1147         return 0;
1148 }
1149
1150 #ifdef USE_GSSAPI
1151
1152 /* Sending an encrypted message is pretty simple - wrap the message in
1153    a token, and send the token.  The server unwraps it to get the
1154    original message.  */
1155 static int send_msg_gss (unsigned char *header, const char *msg, uint32_t mlen)
1156 {
1157         OM_uint32 major_status, minor_status;
1158         gss_buffer_desc utok, etok;
1159         int rc;
1160
1161         utok.length = AUDIT_RMW_HEADER_SIZE + mlen;
1162         utok.value = malloc (utok.length);
1163
1164         memcpy (utok.value, header, AUDIT_RMW_HEADER_SIZE);
1165         
1166         if (msg != NULL && mlen > 0)
1167                 memcpy (utok.value+AUDIT_RMW_HEADER_SIZE, msg, mlen);
1168
1169         major_status = gss_wrap (&minor_status,
1170                                  my_context,
1171                                  1,
1172                                  GSS_C_QOP_DEFAULT,
1173                                  &utok,
1174                                  NULL,
1175                                  &etok);
1176         if (major_status != GSS_S_COMPLETE) {
1177                 gss_failure("encrypting message", major_status, minor_status);
1178                 free (utok.value);
1179                 return -1;
1180         }
1181         rc = send_token (sock, &etok);
1182         free (utok.value);
1183         (void) gss_release_buffer(&minor_status, &etok);
1184
1185         return rc ? -1 : 0;
1186 }
1187
1188 /* Likewise here.  */
1189 static int recv_msg_gss (unsigned char *header, char *msg, uint32_t *mlen)
1190 {
1191         OM_uint32 major_status, minor_status;
1192         gss_buffer_desc utok, etok;
1193         int hver, mver, rc;
1194         uint32_t type, rlen, seq;
1195
1196         rc = recv_token (sock, &etok);
1197         if (rc)
1198                 return -1;
1199
1200         major_status = gss_unwrap (&minor_status, my_context, &etok,
1201                                         &utok, NULL, NULL);
1202         if (major_status != GSS_S_COMPLETE) {
1203                 gss_failure("decrypting message", major_status, minor_status);
1204                 free (utok.value);
1205                 return -1;
1206         }
1207
1208         if (utok.length < AUDIT_RMW_HEADER_SIZE) {
1209                 sync_error_handler ("message too short");
1210                 return -1;
1211         }
1212         memcpy (header, utok.value, AUDIT_RMW_HEADER_SIZE);
1213
1214         if (! AUDIT_RMW_IS_MAGIC (header, AUDIT_RMW_HEADER_SIZE)) {
1215                 sync_error_handler ("bad magic number");
1216                 return -1;
1217         }
1218
1219         AUDIT_RMW_UNPACK_HEADER (header, hver, mver, type, rlen, seq);
1220
1221         if (rlen > MAX_AUDIT_MESSAGE_LENGTH) {
1222                 sync_error_handler ("message too long");
1223                 return -1;
1224         }
1225
1226         memcpy (msg, utok.value+AUDIT_RMW_HEADER_SIZE, rlen);
1227
1228         *mlen = rlen;
1229
1230         return 0;
1231 }
1232 #endif
1233
1234 static int send_msg_tcp (unsigned char *header, const char *msg, uint32_t mlen)
1235 {
1236         int rc;
1237
1238         rc = ar_write(sock, header, AUDIT_RMW_HEADER_SIZE);
1239         if (rc <= 0) {
1240                 syslog(LOG_ERR, "send to %s failed", config.remote_server);
1241                 return 1;
1242         }
1243
1244         if (msg != NULL && mlen > 0) {
1245                 rc = ar_write(sock, msg, mlen);
1246                 if (rc <= 0) {
1247                         syslog(LOG_ERR, "send to %s failed",
1248                                 config.remote_server);
1249                         return 1;
1250                 }
1251         }
1252         return 0;
1253 }
1254
1255 static int recv_msg_tcp (unsigned char *header, char *msg, uint32_t *mlen)
1256 {
1257         int hver, mver, rc;
1258         uint32_t type, rlen, seq;
1259
1260         rc = ar_read (sock, header, AUDIT_RMW_HEADER_SIZE);
1261         if (rc < 16) {
1262                 syslog(LOG_ERR, "read from %s failed", config.remote_server);
1263                 return -1;
1264         }
1265
1266         if (! AUDIT_RMW_IS_MAGIC (header, AUDIT_RMW_HEADER_SIZE)) {
1267                 /* FIXME: the right thing to do here is close the socket
1268                  *  and start a new one.  */
1269                 sync_error_handler ("bad magic number");
1270                 return -1;
1271         }
1272
1273         AUDIT_RMW_UNPACK_HEADER (header, hver, mver, type, rlen, seq);
1274
1275         if (rlen > MAX_AUDIT_MESSAGE_LENGTH) {
1276                 sync_error_handler ("message too long");
1277                 return -1;
1278         }
1279
1280         if (rlen > 0 && ar_read (sock, msg, rlen) < rlen) {
1281                 sync_error_handler ("ran out of data reading reply");
1282                 return -1;
1283         }
1284         return 0;
1285 }
1286
1287 static int check_message_managed(void)
1288 {
1289         unsigned char header[AUDIT_RMW_HEADER_SIZE];
1290         int hver, mver;
1291         uint32_t type, rlen, seq;
1292         char msg[MAX_AUDIT_MESSAGE_LENGTH+1];
1293
1294 #ifdef USE_GSSAPI
1295         if (USE_GSS) {
1296                 if (recv_msg_gss (header, msg, &rlen)) {
1297                         stop_transport();
1298                         return -1;
1299                 }
1300         } else
1301 #endif
1302         if (recv_msg_tcp(header, msg, &rlen)) {
1303                 stop_transport();
1304                 return -1;
1305         }
1306
1307         AUDIT_RMW_UNPACK_HEADER(header, hver, mver, type, rlen, seq);
1308         msg[rlen] = 0;
1309
1310         if (type == AUDIT_RMW_TYPE_ENDING)
1311                 return remote_server_ending_handler(msg);
1312         if (type == AUDIT_RMW_TYPE_DISKLOW)
1313                 return remote_disk_low_handler(msg);
1314         if (type == AUDIT_RMW_TYPE_DISKFULL)
1315                 return remote_disk_full_handler(msg);
1316         if (type == AUDIT_RMW_TYPE_DISKERROR)
1317                 return remote_disk_error_handler(msg);
1318         return -1;
1319 }
1320
1321 /* This is to check for async notification like server is shutting down */
1322 static int check_message(void)
1323 {
1324         int rc;
1325
1326         switch (config.format)
1327         {
1328                 case F_MANAGED:
1329                         rc = check_message_managed();
1330                         break;
1331 /*              case F_ASCII:
1332                         rc = check_message_ascii();
1333                         break; */
1334                 default:
1335                         rc = -1;
1336                         break;
1337         }
1338
1339         return rc;
1340 }
1341
1342 static int relay_sock_managed(const char *s, size_t len)
1343 {
1344         static int sequence_id = 1;
1345         unsigned char header[AUDIT_RMW_HEADER_SIZE];
1346         int hver, mver;
1347         uint32_t type, rlen, seq;
1348         char msg[MAX_AUDIT_MESSAGE_LENGTH+1];
1349         int n_tries_this_message = 0;
1350         time_t now, then = 0;
1351
1352         sequence_id ++;
1353
1354 try_again:
1355         time (&now);
1356         if (then == 0)
1357                 then = now;
1358
1359         /* We want the first retry to be quick, in case the network
1360            failed for some fail-once reason.  In this case, it goes
1361            "failure - reconnect - send".  Only if this quick retry
1362            fails do we start pausing between retries to prevent
1363            swamping the local computer and the network.  */
1364         if (n_tries_this_message > 1)
1365                 sleep (config.network_retry_time);
1366
1367         if (n_tries_this_message > config.max_tries_per_record) {
1368                 network_failure_handler ("max retries exhausted");
1369                 return -1;
1370         }
1371         if ((now - then) > config.max_time_per_record) {
1372                 network_failure_handler ("max retry time exhausted");
1373                 return -1;
1374         }
1375
1376         n_tries_this_message ++;
1377
1378         if (!transport_ok) {
1379                 if (init_transport ())
1380                         goto try_again;
1381         }
1382
1383         type = (s != NULL) ? AUDIT_RMW_TYPE_MESSAGE : AUDIT_RMW_TYPE_HEARTBEAT;
1384         AUDIT_RMW_PACK_HEADER (header, 0, type, len, sequence_id);
1385
1386 #ifdef USE_GSSAPI
1387         if (USE_GSS) {
1388                 if (send_msg_gss (header, s, len)) {
1389                         stop_transport ();
1390                         goto try_again;
1391                 }
1392         } else
1393 #endif
1394         if (send_msg_tcp (header, s, len)) {
1395                 stop_transport ();
1396                 goto try_again;
1397         }
1398
1399 #ifdef USE_GSSAPI
1400         if (USE_GSS) {
1401                 if (recv_msg_gss (header, msg, &rlen)) {
1402                         stop_transport ();
1403                         goto try_again;
1404                 }
1405         } else
1406 #endif
1407         if (recv_msg_tcp (header, msg, &rlen)) {
1408                 stop_transport ();
1409                 goto try_again;
1410         }
1411
1412         AUDIT_RMW_UNPACK_HEADER (header, hver, mver, type, rlen, seq);
1413         msg[rlen] = 0;
1414
1415         /* Handle this first. It doesn't matter if seq compares or not
1416          * since the other end is going down...deal with it. */
1417         if (type == AUDIT_RMW_TYPE_ENDING)
1418                 return remote_server_ending_handler (msg);
1419
1420         if (seq != sequence_id) {
1421                 /* FIXME: should we read another header and
1422                    see if it matches?  If so, we need to deal
1423                    with timeouts.  */
1424                 if (sync_error_handler ("mismatched response"))
1425                         return -1;
1426                 stop_transport();
1427                 goto try_again;
1428         }
1429
1430         /* Specific errors we know how to deal with.  */
1431         if (type == AUDIT_RMW_TYPE_DISKLOW)
1432                 return remote_disk_low_handler (msg);
1433         if (type == AUDIT_RMW_TYPE_DISKFULL)
1434                 return remote_disk_full_handler (msg);
1435         if (type == AUDIT_RMW_TYPE_DISKERROR)
1436                 return remote_disk_error_handler (msg);
1437
1438         /* Generic errors.  */
1439         if (type & AUDIT_RMW_TYPE_FATALMASK)
1440                 return generic_remote_error_handler (msg);
1441         if (type & AUDIT_RMW_TYPE_WARNMASK)
1442                 return generic_remote_warning_handler (msg);
1443
1444         return 0;
1445 }
1446
1447 static int relay_sock(const char *s, size_t len)
1448 {
1449         int rc;
1450
1451         switch (config.format)
1452         {
1453                 case F_MANAGED:
1454                         rc = relay_sock_managed (s, len);
1455                         break;
1456                 case F_ASCII:
1457                         rc = relay_sock_ascii (s, len);
1458                         break;
1459                 default:
1460                         rc = -1;
1461                         break;
1462         }
1463
1464         return rc;
1465 }
1466
1467 /* Send audit event to remote system */
1468 static int relay_event(const char *s, size_t len)
1469 {
1470         int rc;
1471
1472         switch (config.transport)
1473         {
1474                 case T_TCP:
1475                         rc = relay_sock(s, len);
1476                         break;
1477                 default:
1478                         rc = -1;
1479                         break;
1480         }
1481
1482         return rc;
1483 }
1484