Changeset 585


Ignore:
Timestamp:
10/23/11 15:29:16 (3 years ago)
Author:
sgrubb
Message:

Make audisp-remote robust

Location:
branches/1.8
Files:
3 added
15 edited

Legend:

Unmodified
Added
Removed
  • branches/1.8/ChangeLog

    r575 r585  
    1919- Update ausearch parsing 
    2020- Update auparse to handle virt events 
     21- Make audisp-remote robust 
    2122 
    22231.7.18 
  • branches/1.8/audisp/Makefile.am

    r487 r585  
    11# Makefile.am--  
    2 # Copyright 2007 Red Hat Inc., Durham, North Carolina. 
     2# Copyright 2007,2011 Red Hat Inc., Durham, North Carolina. 
    33# All Rights Reserved. 
    44# 
     
    3535        audispd-llist.c queue.c audispd-builtins.c 
    3636audispd_CFLAGS = -fPIE -DPIE -g -D_GNU_SOURCE 
    37 audispd_LDFLAGS = -pie -Wl,-z,relro 
     37audispd_LDFLAGS = -pie -Wl,-z,relro -Wl,-z,now 
    3838 
    3939install-exec-hook: 
  • branches/1.8/audisp/audispd.c

    r227 r585  
    475475} 
    476476 
    477 static int write_to_plugin(event_t *e, lnode *conf) 
     477static int write_to_plugin(event_t *e, const char *string, size_t string_len, 
     478                           lnode *conf) 
    478479{ 
    479480        int rc; 
    480         struct iovec vec[2]; 
    481  
    482         vec[0].iov_base = &e->hdr; 
    483         vec[0].iov_len = sizeof(struct audit_dispatcher_header); 
    484  
    485         vec[1].iov_base = e->data; 
    486         vec[1].iov_len = MAX_AUDIT_MESSAGE_LENGTH; 
    487         do { 
    488                 rc = writev(conf->p->plug_pipe[1], vec, 2); 
    489         } while (rc < 0 && errno == EINTR); 
     481 
     482        if (conf->p->format == F_STRING) { 
     483                do { 
     484                        rc = write(conf->p->plug_pipe[1], string, string_len); 
     485                } while (rc < 0 && errno == EINTR); 
     486        } else { 
     487                struct iovec vec[2]; 
     488 
     489                vec[0].iov_base = &e->hdr; 
     490                vec[0].iov_len = sizeof(struct audit_dispatcher_header); 
     491 
     492                vec[1].iov_base = e->data; 
     493                vec[1].iov_len = MAX_AUDIT_MESSAGE_LENGTH; 
     494                do { 
     495                        rc = writev(conf->p->plug_pipe[1], vec, 2); 
     496                } while (rc < 0 && errno == EINTR); 
     497        } 
    490498        return rc; 
    491499} 
     
    638646                        } else if (conf->p->type == S_ALWAYS) { 
    639647                                int rc; 
    640                                 if (conf->p->format == F_STRING) { 
    641                                         do { 
    642                                                 rc = write( 
    643                                                         conf->p->plug_pipe[1], 
    644                                                         v, len); 
    645                                         } while (rc < 0 && errno == EINTR); 
    646                                 } else { 
    647                                         rc = write_to_plugin(e, conf); 
    648                                 } 
     648                                rc = write_to_plugin(e, v, len, conf); 
    649649                                if (rc < 0 && errno == EPIPE) { 
    650650                                        /* Child disappeared ? */ 
     
    663663                                        conf->p->plug_pipe[1] = -1; 
    664664                                        conf->p->active = A_NO; 
    665                                         if (start_one_plugin(conf) == 0) { 
    666                                                 rc = write_to_plugin(e, conf); 
     665                                        if (start_one_plugin(conf)) { 
     666                                                rc = write_to_plugin(e, v, len, 
     667                                                                     conf); 
    667668                                                syslog(LOG_NOTICE, 
    668669                                                "plugin %s was restarted", 
    669670                                                        conf->p->path); 
     671                                                conf->p->active = A_YES; 
    670672                                        }  
    671673                                } 
  • branches/1.8/audisp/plugins/builtins/syslog.conf

    r1 r585  
    1 # This file controls the configuration of the 
    2 # syslog plugin. It simply takes events and writes 
    3 # them to syslog. 
     1# This file controls the configuration of the syslog plugin. 
     2# It simply takes events and writes them to syslog. The 
     3# arguments provided can be the default priority that you 
     4# want the events written with. And optionally, you can give 
     5# a second argument indicating the facility that you want events 
     6# logged to. Valid options are LOG_LOCAL0 through 7. 
    47 
    58active = no 
  • branches/1.8/audisp/plugins/remote/Makefile.am

    r250 r585  
    11# Makefile.am -- 
    2 # Copyright 2008-2009 Red Hat Inc., Durham, North Carolina. 
     2# Copyright 2008-2009,11 Red Hat Inc., Durham, North Carolina. 
    33# All Rights Reserved. 
    44# 
     
    2222 
    2323CONFIG_CLEAN_FILES = *.loT *.rej *.orig 
    24 EXTRA_DIST = au-remote.conf audisp-remote.conf $(man_MANS) 
    25 AUTOMAKE_OPTIONS = no-dependencies 
     24EXTRA_DIST = au-remote.conf audisp-remote.conf notes.txt $(man_MANS) 
    2625INCLUDES = -I${top_srcdir} -I${top_srcdir}/lib  
    2726prog_confdir = $(sysconfdir)/audisp 
     
    3029plugin_conf = au-remote.conf 
    3130sbin_PROGRAMS = audisp-remote 
    32 noinst_HEADERS = remote-config.h queue.h 
     31noinst_HEADERS = remote-config.h queue.h remote-fgets.h 
    3332man_MANS = audisp-remote.8 audisp-remote.conf.5 
     33check_PROGRAMS = test-queue 
     34TESTS = $(check_PROGRAMS) 
    3435 
    35 audisp_remote_SOURCES = audisp-remote.c remote-config.c queue.c 
     36audisp_remote_SOURCES = audisp-remote.c remote-config.c queue.c remote-fgets.c 
    3637audisp_remote_CFLAGS = -fPIE -DPIE -g -D_REENTRANT -D_GNU_SOURCE -Wundef 
    37 audisp_remote_LDFLAGS = -pie -Wl,-z,relro $(gss_libs) 
     38audisp_remote_LDFLAGS = -pie -Wl,-z,relro -Wl,-z,now $(gss_libs) 
     39 
     40test_queue_SOURCES = queue.c test-queue.c 
    3841 
    3942install-data-hook: 
  • branches/1.8/audisp/plugins/remote/audisp-remote.8

    r1 r585  
    1 .TH AUDISP-REMOTE: "8" "Mar 2008" "Red Hat" "System Administration Utilities" 
     1.TH AUDISP-REMOTE: "8" "Apr 2011" "Red Hat" "System Administration Utilities" 
    22.SH NAME 
    33audisp-remote \- plugin for remote logging  
     
    1010If you are aggregating multiple machines, you should enable node information in the audit event stream. You can do this in one of two places. If you want computer node names written to disk as well as sent in the realtime event stream, edit the name_format option in /etc/audit/auditd.conf. If you only want the node names in the realtime event stream, then edit the name_format option in /etc/audisp/audispd.conf. Do not enable both as it will put 2 node fields in the event stream. 
    1111 
     12.SH SIGNALS 
     13.TP 
     14SIGUSR1 
     15Causes the audisp-remote program to write the value of some of its internal flags to syslog. The 
     16.IR suspend 
     17flag tells whether or not logging has been suspended. The 
     18.IR transport_ok 
     19flag tells whether or not the connection to the remote server is healthy. The 
     20.IR queue_size 
     21tells how many records are enqueued to be sent to the remote server. 
     22.TP 
     23SIGUSR2 
     24Causes the audisp-remote program to resume logging if it were suspended due to an error. 
     25 
    1226.SH FILES 
    1327/etc/audisp/plugins.d/au-remote.conf, /etc/audit/auditd.conf, /etc/audisp/audispd.conf, /etc/audisp/audisp-remote.conf 
  • branches/1.8/audisp/plugins/remote/audisp-remote.c

    r353 r585  
    11/* audisp-remote.c -- 
    2  * Copyright 2008,2009 Red Hat Inc., Durham, North Carolina. 
     2 * Copyright 2008-2011 Red Hat Inc., Durham, North Carolina. 
    33 * All Rights Reserved. 
    44 * 
     
    5050#include "remote-config.h" 
    5151#include "queue.h" 
     52#include "remote-fgets.h" 
    5253 
    5354#define CONFIG_FILE "/etc/audisp/audisp-remote.conf" 
    5455#define BUF_SIZE 32 
     56 
     57/* MAX_AUDIT_MESSAGE_LENGTH, aligned to 4 KB so that an average q_append() only 
     58   writes to two disk disk blocks (1 aligned data block, 1 header block). */ 
     59#define QUEUE_ENTRY_SIZE (3*4096) 
    5560 
    5661/* Error types */ 
     
    6368static volatile int hup = 0; 
    6469static volatile int suspend = 0; 
     70static volatile int dump = 0; 
    6571static volatile int transport_ok = 0; 
    6672static volatile int sock=-1; 
    6773static volatile int remote_ended = 0, quiet = 0; 
    6874static int ifd; 
    69 static FILE *in; 
    70  
     75remote_conf_t config; 
     76 
     77/* Constants */ 
    7178static const char *SINGLE = "1"; 
    7279static const char *HALT = "0"; 
    73 static remote_conf_t config; 
     80static const char *INIT_PGM = "/sbin/init"; 
     81static const char *SPOOL_FILE = "/var/spool/audit/remote.log"; 
    7482 
    7583/* Local function declarations */ 
     
    7886static int init_transport(void); 
    7987static int stop_transport(void); 
    80  
    8188static int ar_read (int, void *, int); 
    8289static int ar_write (int, const void *, int); 
     
    9198#endif 
    9299 
     100/* Compile-time expression verification */ 
     101#define verify(E) do {                          \ 
     102                char verify__[(E) ? 1 : -1];    \ 
     103                (void)verify__;                 \ 
     104        } while (0) 
     105 
    93106/* 
    94107 * SIGTERM handler 
     
    114127 
    115128/* 
     129 * SIGSUR1 handler: dump stats 
     130 */ 
     131static void user1_handler( int sig ) 
     132{ 
     133        dump = 1; 
     134} 
     135 
     136static void dump_stats(struct queue *queue) 
     137{ 
     138        syslog(LOG_INFO, "suspend=%s, transport_ok=%s, queue_size=%zu", 
     139                suspend ? "yes" : "no", 
     140                transport_ok ? "yes" : "no", 
     141                q_queue_length(queue)); 
     142        dump = 0; 
     143} 
     144 
     145/* 
    116146 * SIGSUR2 handler: resume logging 
    117147 */ 
     
    129159                ; /* empty */ 
    130160} 
     161 
    131162/* 
    132163 * Handlers for various events coming back from the remote server. 
     
    141172           doesn't fix it, we eventually call network_failure_handler 
    142173           which has all the user-tweakable actions.  */ 
    143         if (config.network_failure_action == FA_SYSLOG) 
    144                 syslog (LOG_ERR, "lost/losing sync, %s", why); 
     174        syslog (LOG_ERR, "lost/losing sync, %s", why); 
    145175        return 0; 
    146176} 
     
    150180        char *argv[3]; 
    151181        int pid; 
    152         static const char *init_pgm = "/sbin/init"; 
    153182 
    154183        pid = fork(); 
     
    162191 
    163192        /* Child */ 
    164         argv[0] = (char *)init_pgm; 
     193        argv[0] = (char *)INIT_PGM; 
    165194        argv[1] = (char *)level; 
    166195        argv[2] = NULL; 
    167         execve(init_pgm, argv, NULL); 
    168         syslog(LOG_ALERT, "audisp-remote failed to exec %s", init_pgm); 
     196        execve(INIT_PGM, argv, NULL); 
     197        syslog(LOG_ALERT, "audisp-remote failed to exec %s", INIT_PGM); 
    169198        exit(1); 
    170199} 
     
    174203        char *argv[3]; 
    175204        int pid; 
     205 
     206        if (exe == NULL) { 
     207                syslog(LOG_ALERT,   
     208                        "Safe_exec passed NULL for program to execute"); 
     209                return; 
     210        } 
    176211 
    177212        pid = fork(); 
     
    248283static int remote_disk_low_handler (const char *message) 
    249284{ 
    250         return do_action ("remote disk low", message, 
     285        return do_action ("remote server is low on disk space", message, 
    251286                          LOG_WARNING, 
    252287                          config.disk_low_action, config.disk_low_exe); 
     
    255290static int remote_disk_full_handler (const char *message) 
    256291{ 
    257         return do_action ("remote disk full", message, 
     292        return do_action ("remote server's disk is full", message, 
    258293                          LOG_ERR, 
    259294                          config.disk_full_action, config.disk_full_exe); 
     
    262297static int remote_disk_error_handler (const char *message) 
    263298{ 
    264         return do_action ("remote disk error", message, 
     299        return do_action ("remote server has a disk error", message, 
    265300                          LOG_ERR, 
    266301                          config.disk_error_action, config.disk_error_exe); 
     
    271306        stop_transport(); 
    272307        remote_ended = 1; 
    273         return do_action ("remote server ending", message, 
     308        return do_action ("remote server is going down", message, 
    274309                          LOG_NOTICE, 
    275310                          config.remote_ending_action, 
     
    292327} 
    293328 
     329/* Report and handle a queue error, using errno. */ 
     330static void queue_error(void) 
     331{ 
     332        char *errno_str; 
     333 
     334        errno_str = strerror(errno); 
     335        do_action("queue error", errno_str, LOG_ERR, config.queue_error_action, 
     336                  config.queue_error_exe); 
     337} 
     338 
    294339static void send_heartbeat (void) 
    295340{ 
     
    297342} 
    298343 
     344static void do_overflow_action(void) 
     345{ 
     346        switch (config.overflow_action) 
     347        { 
     348                case OA_IGNORE: 
     349                        break; 
     350                case OA_SYSLOG: 
     351                        syslog(LOG_ERR, "queue is full - dropping event"); 
     352                        break; 
     353                case OA_SUSPEND: 
     354                        syslog(LOG_ALERT, 
     355                            "Audisp-remote is suspending event processing due to overflowing its queue."); 
     356                        suspend = 1; 
     357                        break; 
     358                case OA_SINGLE: 
     359                        syslog(LOG_ALERT, 
     360                                "Audisp-remote is now changing the system to single user mode due to overflowing its queue"); 
     361                        change_runlevel(SINGLE); 
     362                        break; 
     363                case OA_HALT: 
     364                        syslog(LOG_ALERT, 
     365                                "Audisp-remote is now halting the system due to overflowing its queue"); 
     366                        change_runlevel(HALT); 
     367                        break; 
     368                default: 
     369                        syslog(LOG_ALERT, "Unknown overflow action requested"); 
     370                        break; 
     371        } 
     372} 
     373 
     374/* Initialize and return a queue depending on user's configuration. 
     375   On error return NULL and set errno. */ 
     376static struct queue *init_queue(void) 
     377{ 
     378        const char *path; 
     379        int q_flags; 
     380 
     381        if (config.queue_file != NULL) 
     382                path = config.queue_file; 
     383        else 
     384                path = SPOOL_FILE; 
     385        q_flags = Q_IN_MEMORY; 
     386        if (config.mode == M_STORE_AND_FORWARD) 
     387                /* FIXME: let user control Q_SYNC? */ 
     388                q_flags |= Q_IN_FILE | Q_CREAT | Q_RESIZE; 
     389        verify(QUEUE_ENTRY_SIZE >= MAX_AUDIT_MESSAGE_LENGTH); 
     390        return q_open(q_flags, path, config.queue_depth, QUEUE_ENTRY_SIZE); 
     391} 
     392 
     393/* Send a record from QUEUE to the remote system */ 
     394static void send_one(struct queue *queue) 
     395{ 
     396        char event[MAX_AUDIT_MESSAGE_LENGTH]; 
     397        int len; 
     398 
     399        if (suspend || !transport_ok) 
     400                return; 
     401 
     402        len = q_peek(queue, event, sizeof(event)); 
     403        if (len == 0) 
     404                return; 
     405        if (len < 0) { 
     406                queue_error(); 
     407                return; 
     408        } 
     409 
     410        /* We send len -1 to remove trailing \n */ 
     411        if (relay_event(event, len-1) < 0) 
     412                return; 
     413 
     414        if (q_drop_head(queue) != 0) 
     415                queue_error(); 
     416} 
     417 
    299418int main(int argc, char *argv[]) 
    300419{ 
    301         event_t *e; 
    302420        struct sigaction sa; 
    303         int rc, q_len; 
     421        struct queue *queue; 
     422        int rc; 
     423        size_t q_len; 
    304424 
    305425        /* Register sighandlers */ 
     
    311431        sa.sa_handler = hup_handler; 
    312432        sigaction(SIGHUP, &sa, NULL); 
     433        sa.sa_handler = user1_handler; 
     434        sigaction(SIGUSR1, &sa, NULL); 
    313435        sa.sa_handler = user2_handler; 
    314436        sigaction(SIGUSR2, &sa, NULL); 
     
    319441 
    320442        // ifd = open("test.log", O_RDONLY); 
    321         // in = fdopen(ifd, "r"); 
    322443        ifd = 0; 
    323         in = stdin; 
     444        fcntl(ifd, F_SETFL, O_NONBLOCK); 
    324445 
    325446        /* We fail here if the transport can't be initialized because of some 
    326          * permenent (i.e. operator) problem, such as misspelled host name. */ 
     447         * permanent (i.e. operator) problem, such as misspelled host name. */ 
    327448        rc = init_transport(); 
    328449        if (rc == ET_PERMANENT) 
    329450                return 1; 
    330         init_queue(config.queue_depth); 
    331  
    332         do { 
    333                 fd_set rfd; 
     451        queue = init_queue(); 
     452        if (queue == NULL) { 
     453                syslog(LOG_ERR, "Error initializing audit record queue: %m"); 
     454                return 1; 
     455        } 
     456 
     457        while (stop == 0) { //FIXME break out when socket is closed 
     458                fd_set rfd, wfd; 
    334459                struct timeval tv; 
     460                char event[MAX_AUDIT_MESSAGE_LENGTH]; 
    335461                int n, fds = ifd + 1; 
    336462 
     
    339465                        reload_config(); 
    340466 
     467                if (dump) 
     468                        dump_stats(queue); 
     469 
     470                /* Setup select flags */ 
    341471                FD_ZERO(&rfd); 
    342472                FD_SET(ifd, &rfd);      // input fd 
     473                FD_ZERO(&wfd); 
    343474                if (sock > 0) { 
     475                        // Setup socket to read acks from server 
    344476                        FD_SET(sock, &rfd); // remote socket 
    345477                        if (sock > ifd) 
    346478                                fds = sock + 1; 
     479                        // If we have anything in the queue, 
     480                        // find out if we can send it 
     481                        if (q_queue_length(queue) && !suspend && transport_ok) 
     482                                FD_SET(sock, &wfd); 
    347483                } 
     484 
    348485                if (config.heartbeat_timeout > 0) { 
    349486                        tv.tv_sec = config.heartbeat_timeout; 
    350487                        tv.tv_usec = 0; 
    351                         n = select(fds, &rfd, NULL, NULL, &tv); 
     488                        n = select(fds, &rfd, &wfd, NULL, &tv); 
    352489                } else 
    353                         n = select(fds, &rfd, NULL, NULL, NULL); 
     490                        n = select(fds, &rfd, &wfd, NULL, NULL); 
    354491                if (n < 0) 
    355                         // If we are here, we had some kind of problem 
    356                         continue; 
     492                        continue; // If here, we had some kind of problem 
    357493 
    358494                if ((config.heartbeat_timeout > 0) && n == 0 && !remote_ended) { 
     
    367503 
    368504                // See if we got a shutdown message from the server 
    369                 if (sock > 0 && FD_ISSET(sock, &rfd)) { 
     505                if (sock > 0 && FD_ISSET(sock, &rfd)) 
    370506                        check_message(); 
     507 
     508                // If we broke out due to one of these, cycle to start 
     509                if (hup != 0 || stop != 0) 
     510                        continue; 
     511 
     512                // See if input fd is also set 
     513                if (FD_ISSET(ifd, &rfd)) { 
     514                        do { 
     515                                if (remote_fgets(event, sizeof(event), ifd)) { 
     516                                        if (!transport_ok && remote_ended &&  
     517                                                config.remote_ending_action == 
     518                                                                 FA_RECONNECT) { 
     519                                                quiet = 1; 
     520                                                if (init_transport() == 
     521                                                                ET_SUCCESS) 
     522                                                        remote_ended = 0; 
     523                                                quiet = 0; 
     524                                        } 
     525                                        /* Strip out EOE records */ 
     526                                        if (strstr(event,"type=EOE msg=audit(")) 
     527                                                continue; 
     528                                        if (q_append(queue, event) != 0) { 
     529                                                if (errno == ENOSPC) 
     530                                                        do_overflow_action(); 
     531                                                else 
     532                                                        queue_error(); 
     533                                        } 
     534                                } else if (remote_fgets_eof()) 
     535                                        stop = 1; 
     536                        } while (remote_fgets_more(sizeof(event))); 
    371537                } 
    372  
    373                 // See if input fd is also set, otherwise we are done 
    374                 if (!FD_ISSET(ifd, &rfd)) 
    375                         continue; 
    376  
    377                 e = (event_t *)malloc(sizeof(event_t)); 
    378                 if (fgets_unlocked(e->data, MAX_AUDIT_MESSAGE_LENGTH, in) && 
    379                                                         hup==0 && stop==0) { 
    380                         if (!transport_ok && remote_ended &&  
    381                                 config.remote_ending_action == FA_RECONNECT) { 
    382                                 quiet = 1; 
    383                                 if (init_transport() == ET_SUCCESS) 
    384                                         remote_ended = 0; 
    385                                 quiet = 0; 
    386                         } 
    387                         /* Strip out EOE records */ 
    388                         if (strstr(e->data,"type=EOE msg=audit(")) { 
    389                                 free(e); 
    390                                 continue; 
    391                         } 
    392                         enqueue(e); 
    393                         rc = 0; 
    394                         while (!suspend && rc >= 0 && transport_ok && 
    395                                                         (e = dequeue(1))) { 
    396                                 rc = relay_event(e->data,  
    397                                         strnlen(e->data, 
    398                                         MAX_AUDIT_MESSAGE_LENGTH)); 
    399                                 if (rc >= 0) { 
    400                                         dequeue(0); // delete it 
    401                                         free(e); 
    402                                 } 
    403                         } 
    404                 } 
    405                 if (feof(in)) 
    406                         break; 
    407         } while (stop == 0); 
    408         close(sock); 
     538                // See if output fd is also set 
     539                if (sock > 0 && FD_ISSET(sock, &wfd))  
     540                        send_one(queue); 
     541        } 
     542        if (sock >= 0) { 
     543                shutdown(sock, SHUT_RDWR); 
     544                close(sock); 
     545        } 
    409546        free_config(&config); 
    410         q_len = queue_length(); 
    411         destroy_queue(); 
     547        q_len = q_queue_length(queue); 
     548        q_close(queue); 
    412549        if (stop) 
    413550                syslog(LOG_NOTICE, "audisp-remote is exiting on stop request"); 
     
    444581                | ((uint32_t)(lenbuf[2] & 0xFF) << 8) 
    445582                |  (uint32_t)(lenbuf[3] & 0xFF)); 
     583 
    446584        if (len > MAX_AUDIT_MESSAGE_LENGTH) { 
    447585                syslog(LOG_ERR, 
    448                         "GSS-API error: event length exceeds MAX_AUDIT_LENGTH"); 
     586                        "GSS-API error: event length excedes MAX_AUDIT_LENGTH"); 
    449587                return -1; 
    450588        } 
     
    579717        token_ptr = GSS_C_NO_BUFFER; 
    580718        *gss_context = GSS_C_NO_CONTEXT; 
     719        recv_tok.value = NULL; 
    581720 
    582721        krberr = krb5_init_context (&kcontext); 
     
    771910static int stop_sock(void) 
    772911{ 
    773         close(sock); 
     912        if (sock >= 0) { 
     913                shutdown(sock, SHUT_RDWR); 
     914                close(sock); 
     915        } 
    774916        sock = -1; 
    775917        transport_ok = 0; 
     
    834976                 
    835977                memset (&address, 0, sizeof(address)); 
    836                 address.sin_family = htons(AF_INET); 
     978                address.sin_family = AF_INET; 
    837979                address.sin_port = htons(config.local_port); 
    838980                address.sin_addr.s_addr = htonl(INADDR_ANY); 
     
    10571199        rc = ar_write(sock, header, AUDIT_RMW_HEADER_SIZE); 
    10581200        if (rc <= 0) { 
    1059                 if (config.network_failure_action == FA_SYSLOG) 
    1060                         syslog(LOG_ERR, "connection to %s closed unexpectedly", 
    1061                                config.remote_server); 
     1201                syslog(LOG_ERR, "send to %s failed", config.remote_server); 
    10621202                return 1; 
    10631203        } 
     
    10661206                rc = ar_write(sock, msg, mlen); 
    10671207                if (rc <= 0) { 
    1068                         if (config.network_failure_action == FA_SYSLOG) 
    1069                                 syslog(LOG_ERR, 
    1070                                        "connection to %s closed unexpectedly", 
    1071                                        config.remote_server); 
     1208                        syslog(LOG_ERR, "send to %s failed", 
     1209                                config.remote_server); 
    10721210                        return 1; 
    10731211                } 
     
    10831221        rc = ar_read (sock, header, AUDIT_RMW_HEADER_SIZE); 
    10841222        if (rc < 16) { 
    1085                 if (config.network_failure_action == FA_SYSLOG) 
    1086                         syslog(LOG_ERR, "connection to %s closed unexpectedly", 
    1087                                config.remote_server); 
     1223                syslog(LOG_ERR, "read from %s failed", config.remote_server); 
    10881224                return -1; 
    10891225        } 
  • branches/1.8/audisp/plugins/remote/audisp-remote.conf

    r250 r585  
    88##local_port = 
    99transport = tcp 
     10queue_file = /var/spool/audit/remote.log 
    1011mode = immediate 
    11 queue_depth = 200 
     12queue_depth = 2048 
    1213format = managed 
    1314network_retry_time = 1 
     
    2324generic_error_action = syslog 
    2425generic_warning_action = syslog 
     26overflow_action = syslog 
    2527 
    26 enable_krb5 = no 
     28##enable_krb5 = no 
    2729##krb5_principal =  
    28 krb5_client_name = auditd 
     30##krb5_client_name = auditd 
    2931##krb5_key_file = /etc/audisp/audisp-remote.key 
  • branches/1.8/audisp/plugins/remote/audisp-remote.conf.5

    r250 r585  
    1 .TH AUDISP-REMOTE.CONF: "5" "Dec 2008" "Red Hat" "System Administration Utilities" 
     1.TH AUDISP-REMOTE.CONF: "5" "Mar 2011" "Red Hat" "System Administration Utilities" 
    22.SH NAME 
    33audisp-remote.conf \- the audisp-remote configuration file 
     
    77.TP 
    88.I remote_server 
    9 This is a one word character string that is the remote server hostname or address that this daemon will send log information to. This can be the numeric address or a resolvable hostname. 
     9This is a one word character string that is the remote server hostname or address that this plugin will send log information to. This can be the numeric address or a resolvable hostname. 
    1010.TP 
    1111.I port 
     
    3333the remote logging app will attempt to send events immediately after getting them. 
    3434.I forward 
    35 , which is not implemented yet, means that it will store the events to disk and then attempt to send the records. If the connection cannot be made, it will queue records until it can connection to the remote system. The depth of the queue is controlled by the 
     35means that it will store the events to disk and then attempt to send the records. If the connection cannot be made, it will queue records until it can connect to the remote system. The depth of the queue is controlled by the 
    3636.I queue_depth 
    3737option. 
     38.TP 
     39.I queue_file 
     40Path of a file used for the event queue if 
     41.I mode 
     42is set to \fIforward\fP.  The default is \fB/var/spool/audit/remote.log\fP. 
    3843.TP 
    3944.I queue_depth 
     
    4247mode of the 
    4348.I mode 
    44 option and internal queueing for temporary network outtages. The default depth is 200. 
     49option and internal queueing for temporary network outtages. The default depth is 2048. 
    4550.TP 
    4651.I format 
     
    5358.I ascii 
    5459is given instead, each message is a simple ASCII text line with no 
    55 overhead at all. 
     60overhead at all.  If 
     61.I mode 
     62is set to \fIforward\fP, 
     63.I format 
     64must be \fImanaged\fP. 
    5665.TP 
    5766.I network_retry_time 
     
    8695If set to 
    8796.IR ignore , 
    88 the audit daemon does nothing. 
     97the remote logging app does nothing. 
    8998.I Syslog 
    9099means that it will issue a warning to syslog.  This is the default. 
     
    128137log it to syslog. 
    129138.TP 
     139.I queue_error_action 
     140Likewise, this parameter tells the system what action to take if there 
     141is a problem working with a local record queue.  The default is to exit. 
     142.TP 
     143.I overflow_action 
     144This parameter tells the system what action to take if the 
     145internal event queue overflows. Valid values are 
     146.IR ignore ", " syslog ", " suspend ", " single ", and " halt " . 
     147If set to 
     148.IR ignore , 
     149the remote logging app does nothing. 
     150.I Syslog 
     151means that it will issue a warning to syslog.  This is the default. 
     152.I Suspend 
     153will cause the remote logging app to stop sending records to the remote system. The logging app will still be alive. The 
     154.I single 
     155option will cause the remote logging app to put the computer system in single user mode. The 
     156.I halt 
     157option will cause the remote logging app to shutdown the computer system. 
     158.TP 
    130159.I enable_krb5 
    131160If set to "yes", Kerberos 5 will be used for authentication and 
  • branches/1.8/audisp/plugins/remote/queue.c

    r353 r585  
    1 /* queue.c -- 
    2  * Copyright 2009 Red Hat Inc., Durham, North Carolina. 
     1/* queue.c - a string queue implementation 
     2 * Copyright 2009, 2011 Red Hat Inc., Durham, North Carolina. 
    33 * All Rights Reserved. 
    44 * 
     
    1919 * Authors: 
    2020 *      Steve Grubb <sgrubb@redhat.com> 
     21 *      Miloslav Trmač <mitr@redhat.com> 
    2122 */ 
    2223 
    2324#include "config.h" 
     25#include <stdio.h> 
     26#include <arpa/inet.h> 
     27#include <errno.h> 
     28#include <fcntl.h> 
     29#include <limits.h> 
     30#include <stddef.h> 
     31#include <stdint.h> 
    2432#include <stdlib.h> 
     33#include <string.h> 
     34#include <sys/stat.h> 
    2535#include <unistd.h> 
    26 #include <syslog.h> 
    2736#include "queue.h" 
    28 #include "remote-config.h" 
    29  
    30 static volatile event_t **q; 
    31 static unsigned int q_next, q_last, q_depth; 
    32 //static const char *SINGLE = "1"; 
    33 //static const char *HALT = "0"; 
    34  
    35  
    36 int init_queue(unsigned int size) 
    37 { 
    38         unsigned int i; 
    39  
    40         q_next = 0; 
    41         q_last = 0; 
    42         q_depth = size; 
    43         q = malloc(q_depth * sizeof(event_t *)); 
     37 
     38struct queue 
     39{ 
     40        int flags;              /* Q_* */ 
     41        int fd;                 /* -1 if !Q_IN_FILE */ 
     42        /* NULL if !Q_IN_MEMORY.  [i] contains a memory copy of the queue entry 
     43           "i", if known - it may be NULL even if entry exists. */ 
     44        unsigned char **memory; 
     45        size_t num_entries; 
     46        size_t entry_size; 
     47        size_t queue_head; 
     48        size_t queue_length; 
     49        unsigned char buffer[]; /* Used only locally within q_peek() */ 
     50}; 
     51 
     52/* Infrastructure */ 
     53 
     54/* Compile-time expression verification */ 
     55#define verify(E) do {                          \ 
     56                char verify__[(E) ? 1 : -1];    \ 
     57                (void)verify__;                 \ 
     58        } while (0) 
     59 
     60/* Like pread(), except that it handles partial reads, and returns 0 on 
     61   success. */ 
     62static int full_pread(int fd, void *buf, size_t size, off_t offset) 
     63{ 
     64        while (size != 0) { 
     65                ssize_t run, res; 
     66 
     67                if (size > SSIZE_MAX) 
     68                        run = SSIZE_MAX; 
     69                else 
     70                        run = size; 
     71                res = pread(fd, buf, run, offset); 
     72                if (res < 0) 
     73                        return -1; 
     74                if (res == 0) { 
     75                        errno = ENXIO; /* Any better value? */ 
     76                        return -1; 
     77                } 
     78                buf = (unsigned char *)buf + res; 
     79                size -= res; 
     80                offset += res; 
     81        } 
     82        return 0; 
     83} 
     84 
     85/* Like pwrite(), except that it handles partial writes, and returns 0 on 
     86   success. */ 
     87static int full_pwrite(int fd, const void *buf, size_t size, off_t offset) 
     88{ 
     89        while (size != 0) { 
     90                ssize_t run, res; 
     91 
     92                if (size > SSIZE_MAX) 
     93                        run = SSIZE_MAX; 
     94                else 
     95                        run = size; 
     96                res = pwrite(fd, buf, run, offset); 
     97                if (res < 0) 
     98                        return -1; 
     99                if (res == 0) { 
     100                        errno = ENXIO; /* Any better value? */ 
     101                        return -1; 
     102                } 
     103                buf = (const unsigned char *)buf + res; 
     104                size -= res; 
     105                offset += res; 
     106        } 
     107        return 0; 
     108} 
     109 
     110/* File format and utilities */ 
     111 
     112/* The mutable part of struct file_header */ 
     113struct fh_state { 
     114        uint32_t queue_head;    /* 0-based index of the first non-empty entry */ 
     115        uint32_t queue_length;  /* [0, num_entries] */ 
     116}; 
     117 
     118/* All integer values are in network byte order (big endian) */ 
     119struct file_header 
     120{ 
     121        uint8_t magic[14];      /* See fh_magic below */ 
     122        uint8_t version;        /* File format version, see FH_VERSION* below */ 
     123        uint8_t reserved;       /* Must be 0 */ 
     124        /* Total file size is (num_entries + 1) * entry_size.  This must fit 
     125           into SIZE_MAX because the "len" parameter of posix_fallocate has 
     126           a size_t type. */ 
     127        uint32_t num_entries;   /* Total number of entries allocated */ 
     128        uint32_t entry_size; 
     129        struct fh_state s; 
     130}; 
     131 
     132/* Contains a '\0' byte to unambiguously mark the file as a binary file. */ 
     133static const uint8_t fh_magic[14] = "\0audisp-remote"; 
     134#define FH_VERSION_0 0x00 
     135 
     136/* Return file position for ENTRY in Q */ 
     137static size_t entry_offset (const struct queue *q, size_t entry) 
     138{ 
     139        return (entry + 1) * q->entry_size; 
     140} 
     141 
     142/* Synchronize Q if required and return 0. 
     143   On error, return -1 and set errno. */ 
     144static int q_sync(struct queue *q) 
     145{ 
     146        if ((q->flags & Q_SYNC) == 0) 
     147                return 0; 
     148        return fdatasync(q->fd); 
     149} 
     150 
     151/* Sync file's fh_state with Q, q_sync (Q), and return 0. 
     152   On error, return -1 and set errno. */ 
     153static int sync_fh_state (struct queue *q) 
     154{ 
     155        struct fh_state s; 
     156 
     157        if (q->fd == -1) 
     158                return 0; 
     159 
     160        s.queue_head = htonl(q->queue_head); 
     161        s.queue_length = htonl(q->queue_length); 
     162        if (full_pwrite(q->fd, &s, sizeof(s), offsetof(struct file_header, s)) 
     163            != 0) 
     164                return -1; 
     165        return q_sync(q); 
     166} 
     167 
     168/* Queue implementation */ 
     169 
     170/* Open PATH for Q, update Q from it, and return 0. 
     171   On error, return -1 and set errno; Q->fd may be set even on error. */ 
     172static int q_open_file(struct queue *q, const char *path) 
     173{ 
     174        int open_flags, fd_flags; 
     175        struct stat st; 
     176        struct file_header fh; 
     177 
     178        open_flags = O_RDWR; 
     179        if ((q->flags & Q_CREAT) != 0) 
     180                open_flags |= O_CREAT; 
     181        if ((q->flags & Q_EXCL) != 0) 
     182                open_flags |= O_EXCL; 
     183        q->fd = open(path, open_flags, S_IRUSR | S_IWUSR); 
     184        if (q->fd == -1) 
     185                return -1; 
     186 
     187        fd_flags = fcntl(q->fd, F_GETFD); 
     188        if (fd_flags < 0) 
     189                return -1; 
     190        if (fcntl(q->fd, F_SETFD, fd_flags | FD_CLOEXEC) == -1) 
     191                return -1; 
     192 
     193        /* File locking in POSIX is pretty much broken... let's hope nobody 
     194           attempts to open a single file twice within the same process. 
     195           open() above has initialized the file offset to 0, so the lockf() 
     196           below affects the whole file. */ 
     197        if (lockf(q->fd, F_TLOCK, 0) != 0) { 
     198                if (errno == EACCES || errno == EAGAIN) 
     199                        errno = EBUSY; /* This makes more sense... */ 
     200                return -1; 
     201        } 
     202 
     203        if (fstat(q->fd, &st) != 0) 
     204                return -1; 
     205        if (st.st_size == 0) { 
     206                verify(sizeof(fh.magic) == sizeof(fh_magic)); 
     207                memcpy(fh.magic, fh_magic, sizeof(fh.magic)); 
     208                fh.version = FH_VERSION_0; 
     209                fh.reserved = 0; 
     210                fh.num_entries = htonl(q->num_entries); 
     211                fh.entry_size = htonl(q->entry_size); 
     212                fh.s.queue_head = htonl(0); 
     213                fh.s.queue_length = htonl(0); 
     214                if (full_pwrite(q->fd, &fh, sizeof(fh), 0) != 0) 
     215                        return -1; 
     216                if (q_sync(q) != 0) 
     217                        return -1; 
     218                if (posix_fallocate(q->fd, 0, 
     219                                    (q->num_entries + 1) * q->entry_size) != 0) 
     220                        return -1; 
     221        } else { 
     222                uint32_t file_entries; 
     223                if (full_pread(q->fd, &fh, sizeof(fh), 0) != 0) 
     224                        return -1; 
     225                if (memcmp(fh.magic, fh_magic, sizeof(fh.magic)) != 0 
     226                    || fh.version != FH_VERSION_0 || fh.reserved != 0 
     227                    || fh.entry_size != htonl(q->entry_size)) { 
     228                        errno = EINVAL; 
     229                        return -1; 
     230                } 
     231                file_entries = ntohl(fh.num_entries); 
     232                if (file_entries > SIZE_MAX / q->entry_size - 1 
     233                    || ((uintmax_t)st.st_size 
     234                        != (file_entries + 1) * q->entry_size)) { 
     235                        errno = EINVAL; 
     236                        return -1; 
     237                } 
     238        } 
     239        /* Note that this may change q->num_entries! */ 
     240        q->num_entries = ntohl(fh.num_entries); 
     241        q->queue_head = ntohl(fh.s.queue_head); 
     242        q->queue_length = ntohl(fh.s.queue_length); 
     243        if (q->queue_head >= q->num_entries 
     244            || q->queue_length > q->num_entries) { 
     245                errno = EINVAL; 
     246                return -1; 
     247        } 
     248        return 0; 
     249} 
     250 
     251/* Like q_open(), but does not handle Q_RESIZE, and NUM_ENTRIES is only used 
     252   when creating a new file. */ 
     253static struct queue *q_open_no_resize(int q_flags, const char *path, 
     254                                      size_t num_entries, size_t entry_size) 
     255{ 
     256        struct queue *q; 
     257        int saved_errno; 
     258 
     259        if ((q_flags & (Q_IN_MEMORY | Q_IN_FILE)) == 0) { 
     260                errno = EINVAL; 
     261                return NULL; 
     262        } 
     263        if (num_entries == 0 || num_entries > UINT32_MAX 
     264            || entry_size < 1 /* for trailing NUL */ 
     265            || entry_size < sizeof(struct file_header) /* for Q_IN_FILE */ 
     266            /* to allocate "struct queue" including its buffer*/ 
     267            || entry_size > UINT32_MAX - sizeof(struct queue)) { 
     268                errno = EINVAL; 
     269                return NULL; 
     270        } 
     271        if (entry_size > SIZE_MAX 
     272            || num_entries > SIZE_MAX / entry_size - 1 /* for Q_IN_FILE */ 
     273            || num_entries > SIZE_MAX / sizeof(*q->memory)) { 
     274                errno = EINVAL; 
     275                return NULL; 
     276        } 
     277 
     278        q = malloc(sizeof(*q) + entry_size); 
    44279        if (q == NULL) 
    45                 return -1; 
    46  
    47         for (i=0; i<q_depth; i++)  
    48                 q[i] = NULL; 
     280                return NULL; 
     281        q->flags = q_flags; 
     282        q->fd = -1; 
     283        q->memory = NULL; 
     284        q->num_entries = num_entries; 
     285        q->entry_size = entry_size; 
     286        q->queue_head = 0; 
     287        q->queue_length = 0; 
     288 
     289        if ((q_flags & Q_IN_MEMORY) != 0) { 
     290                size_t sz = num_entries * sizeof(*q->memory); 
     291 
     292                q->memory = malloc(sz); 
     293                if (q->memory == NULL) 
     294                        goto err; 
     295                memset(q->memory, 0, sz); 
     296        } 
     297 
     298        if ((q_flags & Q_IN_FILE) != 0 && q_open_file(q, path) != 0) 
     299                goto err; 
     300 
     301        return q; 
     302 
     303err: 
     304        saved_errno = errno; 
     305        if (q->fd != -1) 
     306                close(q->fd); 
     307        free(q->memory); 
     308        free(q); 
     309        errno = saved_errno; 
     310        return NULL; 
     311} 
     312 
     313void q_close(struct queue *q) 
     314{ 
     315        if (q->fd != -1) 
     316                close(q->fd); /* Also releases the file lock */ 
     317        if (q->memory != NULL) { 
     318                size_t i; 
     319 
     320                for (i = 0; i < q->num_entries; i++) 
     321                        free(q->memory[i]); 
     322                free(q->memory); 
     323        } 
     324        free(q); 
     325} 
     326 
     327/* Internal use only: add DATA to Q, but don't update fh_state. */ 
     328static int q_append_no_sync_fh_state(struct queue *q, const char *data) 
     329{ 
     330        size_t data_size, entry_index; 
     331        unsigned char *copy; 
     332 
     333        if (q->queue_length == q->num_entries) { 
     334                errno = ENOSPC; 
     335                return -1; 
     336        } 
     337 
     338        data_size = strlen(data) + 1; 
     339        if (data_size > q->entry_size) { 
     340                errno = EINVAL; 
     341                return -1; 
     342        } 
     343 
     344        entry_index = (q->queue_head + q->queue_length) % q->num_entries; 
     345        if (q->memory != NULL) { 
     346                if (q->memory[entry_index] != NULL) { 
     347                        errno = EIO; /* This is _really_ unexpected. */ 
     348                        return -1; 
     349                } 
     350                copy = malloc(data_size); 
     351                if (copy == NULL) 
     352                        return -1; 
     353                memcpy(copy, data, data_size); 
     354        } else 
     355                copy = NULL; 
     356 
     357        if (q->fd != -1) { 
     358                size_t offset; 
     359 
     360                offset = entry_offset(q, entry_index); 
     361                if (full_pwrite(q->fd, data, data_size, offset) != 0) { 
     362                        int saved_errno; 
     363 
     364                        saved_errno = errno; 
     365                        if (copy != NULL) 
     366                                free(copy); 
     367                        errno = saved_errno; 
     368                        return -1; 
     369                } 
     370        } 
     371 
     372        if (copy != NULL) 
     373                q->memory[entry_index] = copy; 
     374 
     375        q->queue_length++; 
    49376 
    50377        return 0; 
    51378} 
    52379 
    53 /* static void change_runlevel(const char *level) 
    54 { 
    55         char *argv[3]; 
    56         int pid; 
    57         static const char *init_pgm = "/sbin/init"; 
    58  
    59         pid = fork(); 
    60         if (pid < 0) { 
    61                 syslog(LOG_ALERT, "Audispd failed to fork switching runlevels"); 
    62                 return; 
    63         } 
    64         if (pid)        // Parent 
    65                 return; 
    66         // Child 
    67         argv[0] = (char *)init_pgm; 
    68         argv[1] = (char *)level; 
    69         argv[2] = NULL; 
    70         execve(init_pgm, argv, NULL); 
    71         syslog(LOG_ALERT, "Audispd failed to exec %s", init_pgm); 
    72         exit(1); 
    73 } 
    74  
    75 static void do_overflow_action(remote_conf_t *config) 
    76 { 
    77         switch (config->generic_error_action) // FIXME: overflow action var 
    78         { 
    79                 case FA_IGNORE: 
     380int q_append(struct queue *q, const char *data) 
     381{ 
     382        int r; 
     383 
     384        r = q_append_no_sync_fh_state(q, data); 
     385        if (r != 0) 
     386                return r; 
     387 
     388        return sync_fh_state(q); /* Calls q_sync() */ 
     389} 
     390 
     391int q_peek(struct queue *q, char *buf, size_t size) 
     392{ 
     393        const unsigned char *data; 
     394        size_t data_size; 
     395 
     396        if (q->queue_length == 0) 
     397                return 0; 
     398 
     399        if (q->memory != NULL && q->memory[q->queue_head] != NULL) { 
     400                data = q->memory[q->queue_head]; 
     401                data_size = strlen((char *)data) + 1; 
     402        } else if (q->fd != -1) { 
     403                const unsigned char *end; 
     404 
     405                if (full_pread(q->fd, q->buffer, q->entry_size, 
     406                               entry_offset(q, q->queue_head)) != 0) 
     407                        return -1; 
     408                data = q->buffer; 
     409                end = memchr(q->buffer, '\0', q->entry_size); 
     410                if (end == NULL) { 
     411                        /* FIXME: silently drop this entry? */ 
     412                        errno = EBADMSG; 
     413                        return -1; 
     414                } 
     415                data_size = (end - data) + 1; 
     416 
     417                if (q->memory != NULL) { 
     418                        unsigned char *copy; 
     419 
     420                        copy = malloc(data_size); 
     421                        if (copy != NULL) { /* Silently ignore failures. */ 
     422                                memcpy(copy, data, data_size); 
     423                                q->memory[q->queue_head] = copy; 
     424                        } 
     425                } 
     426        } else { 
     427                errno = EIO; /* This is _really_ unexpected. */ 
     428                return -1; 
     429        } 
     430 
     431        if (size < data_size) { 
     432                errno = ERANGE; 
     433                return -1; 
     434        } 
     435        memcpy(buf, data, data_size); 
     436        return data_size; 
     437} 
     438 
     439/* Internal use only: drop head of Q, but don't write this into the file */ 
     440static int q_drop_head_memory_only(struct queue *q) 
     441{ 
     442        if (q->queue_length == 0) { 
     443                errno = EINVAL; 
     444                return -1; 
     445        } 
     446 
     447        if (q->memory != NULL) { 
     448                free(q->memory[q->queue_head]); 
     449                q->memory[q->queue_head] = NULL; 
     450        } 
     451 
     452        q->queue_head++; 
     453        if (q->queue_head == q->num_entries) 
     454                q->queue_head = 0; 
     455        q->queue_length--; 
     456        return 0; 
     457} 
     458 
     459int q_drop_head(struct queue *q) 
     460{ 
     461        int r; 
     462 
     463        r = q_drop_head_memory_only(q); 
     464        if (r != 0) 
     465                return r; 
     466 
     467        return sync_fh_state(q); /* Calls q_sync() */ 
     468} 
     469 
     470size_t q_queue_length(const struct queue *q) 
     471{ 
     472        return q->queue_length; 
     473} 
     474 
     475struct queue *q_open(int q_flags, const char *path, size_t num_entries, 
     476                     size_t entry_size) 
     477{ 
     478        struct queue *q, *q2; 
     479        char *tmp_path, *buf; 
     480        size_t path_len; 
     481        int saved_errno, fd; 
     482 
     483        q = q_open_no_resize(q_flags, path, num_entries, entry_size); 
     484        if (q == NULL || q->num_entries == num_entries) 
     485                return q; 
     486 
     487        if ((q->flags & Q_RESIZE) == 0) { 
     488                saved_errno = EINVAL; 
     489                goto err_errno_q; 
     490        } 
     491 
     492        if (q->queue_length > num_entries) { 
     493                saved_errno = ENOSPC; 
     494                goto err_errno_q; 
     495        } 
     496 
     497        buf = malloc(entry_size); 
     498        if (buf == NULL) { 
     499                saved_errno = errno; 
     500                goto err_errno_q; 
     501        } 
     502 
     503        path_len = strlen(path); 
     504        tmp_path = malloc(path_len + 7); 
     505        if (tmp_path == NULL) { 
     506                saved_errno = errno; 
     507                goto err_errno_buf; 
     508        } 
     509        memcpy(tmp_path, path, path_len); 
     510        memcpy(tmp_path + path_len, "XXXXXX", 7); 
     511        /* We really want tmpnam() here (safe due to the Q_EXCL below), but gcc 
     512           warns on any use of tmpnam(). */ 
     513        fd = mkstemp(tmp_path); 
     514        if (fd == -1) { 
     515                saved_errno = errno; 
     516                goto err_errno_tmp_path; 
     517        } 
     518        if (close(fd) != 0 || unlink(tmp_path) != 0) { 
     519                saved_errno = errno; 
     520                goto err_errno_tmp_file; 
     521        } 
     522 
     523        q2 = q_open_no_resize(q_flags | Q_CREAT | Q_EXCL, tmp_path, num_entries, 
     524                              entry_size); 
     525        if (q2 == NULL) { 
     526                saved_errno = errno; 
     527                goto err_errno_tmp_file; 
     528        } 
     529        if (q2->num_entries != num_entries) { 
     530                errno = EIO;    /* This is _really_ unexpected. */ 
     531                goto err_q2; 
     532        } 
     533 
     534        for (;;) { 
     535                int r; 
     536 
     537                r = q_peek(q, buf, entry_size); 
     538                if (r == 0) 
    80539                        break; 
    81                 case FA_SYSLOG: 
    82                         syslog(LOG_ERR, "queue is full - dropping event"); 
    83                         break; 
    84                 case FA_SUSPEND: 
    85                         syslog(LOG_ALERT, 
    86                             "Audispd-remote is suspending event processing due to overflowing its queue."); 
    87                         break; 
    88                 case FA_SINGLE: 
    89                         syslog(LOG_ALERT, 
    90                                 "Audispd-remote is now changing the system to single user mode due to overflowing its queue"); 
    91                         change_runlevel(SINGLE); 
    92                         break; 
    93                 case FA_HALT: 
    94                         syslog(LOG_ALERT, 
    95                                 "Audispd-remote is now halting the system due to overflowing its queue"); 
    96                         change_runlevel(HALT); 
    97                         break; 
    98                 default: 
    99                         syslog(LOG_ALERT, "Unknown overflow action requested"); 
    100                         break; 
    101         } 
    102 } */ 
    103  
    104 void enqueue(event_t *e) 
    105 { 
    106         unsigned int n; 
    107  
    108         // OK, add event 
    109         n = q_next%q_depth; 
    110         if (q[n] == NULL) { 
    111                 q[n] = e; 
    112                 q_next = (n+1) % q_depth; 
    113         } else { 
    114 // FIXME: overflow 
    115         } 
    116 } 
    117  
    118 event_t *dequeue(int peek) 
    119 { 
    120         event_t *e; 
    121         unsigned int n; 
    122  
    123         // OK, grab the next event 
    124         n = q_last%q_depth; 
    125         if (q[n] != NULL) { 
    126                 e = (event_t *)q[n]; 
    127                 if (peek == 0) { 
    128                         q[n] = NULL; 
    129                         q_last = (n+1) % q_depth; 
    130                 } 
    131         } else 
    132                 e = NULL; 
    133  
    134         // Process the event 
    135         return e; 
    136 } 
    137  
    138 /* void increase_queue_depth(unsigned int size) 
    139 { 
    140         if (size > q_depth) { 
    141                 int i; 
    142                 void *tmp_q; 
    143  
    144                 tmp_q = realloc(q, size * sizeof(event_t *)); 
    145                 q = tmp_q; 
    146                 for (i=q_depth; i<size; i++) 
    147                         q[i] = NULL; 
    148                 q_depth = size; 
    149         } 
    150 } */ 
    151  
    152 int queue_length(void) 
    153 { 
    154         if (q_next == q_last) 
    155                 return 0; 
    156         if (q_last > q_next) 
    157                 return (q_depth + q_next) - q_last; 
    158         else 
    159                 return q_next - q_last; 
    160 } 
    161  
    162 void destroy_queue(void) 
    163 { 
    164         unsigned int i; 
    165  
    166         for (i=0; i<q_depth; i++) 
    167                 free((void *)q[i]); 
    168  
    169         free(q); 
    170 } 
    171  
     540                if (r < 0) 
     541                        goto err_q2; 
     542 
     543                if (q_append_no_sync_fh_state(q2, buf) != 0) 
     544                        goto err_q2; 
     545                if (q_drop_head_memory_only(q) != 0) 
     546                        goto err_q2; 
     547        } 
     548        if (sync_fh_state(q2) != 0) 
     549                goto err_q2; 
     550 
     551        if (rename(tmp_path, path) != 0) 
     552                goto err_q2; 
     553 
     554        q_close(q); 
     555        free(buf); 
     556        free(tmp_path); 
     557        return q2; 
     558 
     559err_q2: 
     560        saved_errno = errno; 
     561        q_close(q2); 
     562err_errno_tmp_file: 
     563        unlink(tmp_path); 
     564err_errno_tmp_path: 
     565        free(tmp_path); 
     566err_errno_buf: 
     567        free(buf); 
     568err_errno_q: 
     569        q_close(q); 
     570        errno = saved_errno; 
     571        return NULL; 
     572} 
  • branches/1.8/audisp/plugins/remote/queue.h

    r353 r585  
    1 /* queue.h -- 
    2  * Copyright 2009 Red Hat Inc., Durham, North Carolina. 
     1/* queue.h -- a queue abstraction 
     2 * Copyright 2009, 2011 Red Hat Inc., Durham, North Carolina. 
    33 * All Rights Reserved. 
    44 * 
     
    1919 * Authors: 
    2020 *      Steve Grubb <sgrubb@redhat.com> 
     21 *      Miloslav Trmač <mitr@redhat.com> 
    2122 */ 
    2223 
     
    2425#define QUEUE_HEADER 
    2526 
    26 #include "libaudit.h" 
     27#include <sys/types.h> 
    2728 
    28 typedef struct event 
    29 { 
    30         char data[MAX_AUDIT_MESSAGE_LENGTH]; 
    31 } event_t; 
     29struct queue; 
    3230 
     31enum { 
     32        // Queue storage.  Both options can be set at the same time. 
     33        Q_IN_MEMORY = 1 << 0,   // Keep a copy of the queue in memory 
     34        Q_IN_FILE = 1 << 1,     // Store the queue in a file 
     35        // Other flags for use with Q_IN_FILE  
     36        Q_CREAT = 1 << 2,       // Create the queue if it does not exist 
     37        Q_EXCL = 1 << 3,        // With Q_CREAT, don't open an existing queue 
     38        Q_SYNC = 1 << 4,        // fdatasync() after each operation 
     39        Q_RESIZE = 1 << 5,      // resize the queue if needed 
     40}; 
    3341 
    34 int init_queue(unsigned int size); 
    35 void enqueue(event_t *e); 
    36 event_t *dequeue(int peek); 
    37 void increase_queue_depth(unsigned int size); 
    38 int queue_length(void); 
    39 void destroy_queue(void); 
     42/* Open a queue using Q_FLAGS and return it. If Q_IN_FILE: use PATH for the 
     43 * file, NUM_ENTRIES must be the same for all users of the file unless Q_RESIZE 
     44 * is set. ENTRY_SIZE is the maximum length of a stored string, including the 
     45 * trailing NUL. If Q_IN_FILE, it must be the same for all users of the file. 
     46 * On error, return NULL and set errno. */ 
     47struct queue *q_open(int q_flags, const char *path, size_t num_entries, 
     48                     size_t entry_size); 
     49/* Close Q. */ 
     50void q_close(struct queue *q); 
     51 
     52/* Add DATA to tail of Q. Return 0 on success, -1 on error and set errno. */ 
     53int q_append(struct queue *q, const char *data); 
     54 
     55/* Peek at head of Q, storing it into BUF of SIZE. Return 1 if an entry  
     56 * exists, 0 if queue is empty. On error, return -1 and set errno. */ 
     57int q_peek(struct queue *q, char *buf, size_t size); 
     58 
     59/* Drop head of Q and return 0. On error, return -1 and set errno. */ 
     60int q_drop_head(struct queue *q); 
     61 
     62/* Return the number of entries in Q. */ 
     63size_t q_queue_length(const struct queue *q);  
    4064 
    4165#endif 
  • branches/1.8/audisp/plugins/remote/remote-config.c

    r251 r585  
    11/* remote-config.c --  
    2  * Copyright 2008, 2009 Red Hat Inc., Durham, North Carolina. 
     2 * Copyright 2008, 2009, 2011 Red Hat Inc., Durham, North Carolina. 
    33 * All Rights Reserved. 
    44 * 
     
    6969static int mode_parser(struct nv_pair *nv, int line,  
    7070                remote_conf_t *config); 
     71static int queue_file_parser(struct nv_pair *nv, int line, 
     72                remote_conf_t *config); 
    7173static int depth_parser(struct nv_pair *nv, int line,  
    7274                remote_conf_t *config); 
     
    9799AP(generic_error) 
    98100AP(generic_warning) 
     101AP(queue_error) 
    99102#undef AP 
    100103static int remote_ending_action_parser(struct nv_pair *nv, int line, 
    101104                remote_conf_t *config); 
     105static int overflow_action_parser(struct nv_pair *nv, int line,  
     106                remote_conf_t *config); 
    102107static int sanity_check(remote_conf_t *config, const char *file); 
    103108 
     
    109114  {"transport",        transport_parser,        0 }, 
    110115  {"mode",             mode_parser,             0 }, 
     116  {"queue_file",       queue_file_parser,       0 }, 
    111117  {"queue_depth",      depth_parser,            0 }, 
    112118  {"format",           format_parser,           0 }, 
     
    126132  {"generic_error_action",   generic_error_action_parser,       1 }, 
    127133  {"generic_warning_action", generic_warning_action_parser,     1 }, 
     134  {"queue_error_action",     queue_error_action_parser,         1 }, 
     135  {"overflow_action",        overflow_action_parser,            1 }, 
    128136  { NULL,                    NULL,                              0 } 
    129137}; 
     
    138146{ 
    139147  {"immediate",  M_IMMEDIATE }, 
    140 //  {"forward",    M_STORE_AND_FORWARD }, 
     148  {"forward",    M_STORE_AND_FORWARD }, 
    141149  { NULL,  0 } 
    142150}; 
     
    154162}; 
    155163 
     164static const struct nv_list overflow_action_words[] = 
     165{ 
     166  {"ignore",   OA_IGNORE }, 
     167  {"syslog",   OA_SYSLOG }, 
     168  {"suspend",  OA_SUSPEND }, 
     169  {"single",   OA_SINGLE }, 
     170  {"halt",     OA_HALT }, 
     171  { NULL,  0 } 
     172}; 
     173 
    156174static const struct nv_list format_words[] = 
    157175{ 
     
    180198        config->transport = T_TCP; 
    181199        config->mode = M_IMMEDIATE; 
    182         config->queue_depth = 200; 
     200        config->queue_file = NULL; 
     201        config->queue_depth = 2048; 
    183202        config->format = F_MANAGED; 
    184203 
     
    196215        IA(generic_error, FA_SYSLOG); 
    197216        IA(generic_warning, FA_SYSLOG); 
     217        IA(queue_error, FA_STOP); 
    198218#undef IA 
     219        config->overflow_action = OA_SYSLOG; 
    199220 
    200221        config->enable_krb5 = 0; 
     
    530551} 
    531552 
     553static int queue_file_parser(struct nv_pair *nv, int line, 
     554                remote_conf_t *config) 
     555{ 
     556        if (nv->value) { 
     557                if (*nv->value != '/') { 
     558                        syslog(LOG_ERR, "Absolute path needed for %s - line %d", 
     559                               nv->value, line); 
     560                        return 1; 
     561                } 
     562                config->queue_file = strdup(nv->value); 
     563        } else 
     564                config->queue_file = NULL; 
     565        return 0; 
     566} 
     567 
    532568static int depth_parser(struct nv_pair *nv, int line, 
    533569                remote_conf_t *config) 
     
    542578        for (i=0; fail_action_words[i].name != NULL; i++) { 
    543579                if (strcasecmp(nv->value, fail_action_words[i].name) == 0) { 
    544                         if (i == FA_EXEC) { 
     580                        if (fail_action_words[i].option == FA_EXEC) { 
    545581                                if (check_exe_name(nv->option, line)) 
    546582                                        return 1; 
     
    568604AP(generic_error) 
    569605AP(generic_warning) 
     606AP(queue_error) 
    570607#undef AP 
     608 
     609static int overflow_action_parser(struct nv_pair *nv, int line, 
     610        remote_conf_t *config) 
     611{ 
     612        int i; 
     613 
     614        for (i=0; overflow_action_words[i].name != NULL; i++) { 
     615                if (strcasecmp(nv->value, overflow_action_words[i].name) == 0) { 
     616                        config->overflow_action = overflow_action_words[i].option; 
     617                        return 0; 
     618                } 
     619        } 
     620        syslog(LOG_ERR, "Option %s not found - line %d", nv->value, line); 
     621        return 1; 
     622} 
    571623 
    572624static int remote_ending_action_parser(struct nv_pair *nv, int line, 
     
    701753// queue_depth should be less than 100k 
    702754// If fail_action is F_EXEC, fail_exec must exist 
     755        if (config->mode == M_STORE_AND_FORWARD 
     756            && config->format != F_MANAGED) { 
     757                syslog(LOG_ERR, "\"mode=forward\" is valid only with " 
     758                       "\"format=managed\""); 
     759                return 1; 
     760        } 
    703761        return 0; 
    704762} 
     
    707765{ 
    708766        free((void *)config->remote_server); 
     767        free((void *)config->queue_file); 
    709768        free((void *)config->network_failure_exe); 
    710769        free((void *)config->disk_low_exe); 
     
    714773        free((void *)config->generic_error_exe); 
    715774        free((void *)config->generic_warning_exe); 
     775        free((void *)config->queue_error_exe); 
    716776        free((void *)config->krb5_principal); 
    717777        free((void *)config->krb5_client_name); 
  • branches/1.8/audisp/plugins/remote/remote-config.h

    r227 r585  
    11/* remote-config.h --  
    2  * Copyright 2008, 2009 Red Hat Inc., Durham, North Carolina. 
     2 * Copyright 2008, 2009, 2011 Red Hat Inc., Durham, North Carolina. 
    33 * All Rights Reserved. 
    44 * 
     
    3030typedef enum { FA_IGNORE, FA_SYSLOG, FA_EXEC, FA_RECONNECT, FA_SUSPEND, 
    3131               FA_SINGLE, FA_HALT, FA_STOP } failure_action_t; 
     32typedef enum { OA_IGNORE, OA_SYSLOG, OA_SUSPEND, OA_SINGLE, 
     33               OA_HALT } overflow_action_t; 
    3234 
    3335typedef struct remote_conf 
     
    3739        unsigned int local_port; 
    3840        transport_t transport; 
    39         mode_t mode; 
     41        rmode_t mode; 
     42        const char *queue_file; 
    4043        unsigned int queue_depth; 
    4144        format_t format; 
     
    6366        failure_action_t generic_warning_action; 
    6467        const char *generic_warning_exe; 
     68        failure_action_t queue_error_action; 
     69        const char *queue_error_exe; 
     70        overflow_action_t overflow_action; 
    6571} remote_conf_t; 
    6672 
  • branches/1.8/audisp/plugins/zos-remote/Makefile.am

    r134 r585  
    11# Makefile.am-- 
    2 # Copyright (C) 2007,2008 International Business Machines  Corp. 
     2# Copyright (C) 2007,2008,2011 International Business Machines  Corp. 
    33# All Rights Reserved. 
    44# 
     
    3737audispd_zos_remote_SOURCES = zos-remote-plugin.c zos-remote-log.c \ 
    3838        zos-remote-ldap.c zos-remote-config.c zos-remote-queue.c 
    39 audispd_zos_remote_CFLAGS = -W -Wall -Wundef -D_GNU_SOURCE 
     39audispd_zos_remote_CFLAGS = -W -Wall -Wundef -D_GNU_SOURCE -fPIE -DPIE 
     40audispd_zos_remote_LDFLAGS = -pie -Wl,-z,relro 
    4041 
    4142install-data-hook: 
  • branches/1.8/audisp/plugins/zos-remote/zos-remote-plugin.c

    r1 r585  
    481481                /* initialize auparse */ 
    482482                au = auparse_init(AUSOURCE_FEED, 0);               /* 2 */ 
     483                if (au == NULL) { 
     484                        log_err("Error - exiting due to auparse init errors"); 
     485                        return -1; 
     486                } 
    483487                 
    484488                /*  
Note: See TracChangeset for help on using the changeset viewer.