/* $CoreSDI: attr_classic.c,v 1.24 2001/11/16 22:52:59 claudio Exp $ */ /* * Copyright (c) 2000, 2001, Core SDI S.A., Argentina * All rights reserved * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither name of the Core SDI S.A. nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * Classic attribute module to handle standard syslog files. * Author: Claudio Castiglia */ #include #include #include #include #include /* XXX: remove when using built-in gzip */ #ifdef __linux__ #include /* in_addr_t */ #endif #include #include #include #include #include #include #include #include #include #include "sysdep.h" #include "resource.h" #include "packet.h" #include "modtypes.h" #include "iaargs.h" #include "log.h" #define ATTR_CLASSIC "attr classic: " #define OFFSET_PREFIX "FileOffset_" /* offset resource prefix */ typedef struct _classic_ctx { char *logset_name; /* logfile name */ struct stat st; /* logfile stat */ RESOURCE *roffset; /* offset resource */ off_t offset; /* logfile offset */ off_t pos; /* internal variable */ off_t prev_size; /* internal variable */ int fd; /* internal variable */ } CLASSIC_CTX; #define GET_CLASSIC_CTX(c) (CLASSIC_CTX *) (c + 1) /* * _type(): * Fills a string with the logfile type: "regular" or "other". */ static char * _type(char *dst, mode_t mode, size_t dst_size) { snprintf(dst, dst_size, "%s", (S_ISREG(mode) ? "regular" : "other")); return (dst); } /* * _uperm(): * Fills a string with user permissions. */ static char * _perm(char *dst, mode_t mode, size_t rflag, size_t wflag, size_t xflag) { dst[0] = dst[1] = dst[2] = '-'; if (mode & rflag) dst[0] = 'r'; if (mode & wflag) dst[1] = 'w'; if (mode & xflag) dst[2] = 'x'; dst[3] = '\0'; return (dst); } /* * _time(): * Do a ctime_r(3) and remove the ending '\n'. */ static char * _time(time_t *t, char *dst) { ctime_r(t, dst); dst[strlen(dst) - 1] = '\0'; return (dst); } /* * _load_offset(): * Search offset resource data and update offset context member. */ static void _load_offset(ATTRCON *context) { char rname[MAXPATHLEN]; CLASSIC_CTX *cc; cc = GET_CLASSIC_CTX(context); if (cc->offset >= 0) return; snprintf(rname, sizeof(rname), OFFSET_PREFIX "%s", cc->logset_name); /* Get offset resource */ if (context->s->s_rlist != NULL) cc->roffset = res_find(context->s->s_rlist, rname); /* Convert resource offset to off_t */ if (cc->roffset == NULL) cc->offset = 0; else { if (cc->roffset->dsize == sizeof(cc->offset)) cc->offset = *(off_t *)cc->roffset->data; else { log_warn(ATTR_CLASSIC "Invalid resource size: %s. " "Ignoring.", rname); cc->offset = 0; } } } /* * _save_offset: * Save current offset into the resource list. * Return 0 on success and -1 on error and set errno. */ static int _save_offset(ATTRCON *context) { char rname[MAXPATHLEN]; int error; CLASSIC_CTX *cc; cc = GET_CLASSIC_CTX(context); if (cc->offset < 0) return (0); error = 0; if (context->s->s_rlist != NULL) { /* If resource does not exists create one */ if (cc->roffset == NULL) { snprintf(rname, sizeof(rname), OFFSET_PREFIX "%s", cc->logset_name); error = res_add(context->s->s_rlist, rname, &cc->offset, sizeof(cc->offset)); } else /* If resource exists replace current data */ error = res_replace(context->s->s_rlist, cc->roffset, &cc->offset, sizeof(cc->offset)); } return (error); } /* * _copy(): * Copy data from one fd to another or same fd. */ static int _copy(int dstfd, int srcfd, off_t dstoff, off_t srcoff, off_t size) { char buf[BUFSIZ]; ssize_t to_read, to_write; if (lseek(dstfd, dstoff, SEEK_SET) < 0 || lseek(srcfd, srcoff, SEEK_SET) < 0) return (-1); while (size) { to_read = (size > sizeof(buf)) ? sizeof(buf) : size; to_write = read(srcfd, buf, to_read); if (to_write < 0) return (-1); if (dstfd == srcfd) { if (lseek(dstfd, dstoff, SEEK_SET) < 0) return (-1); srcoff += to_write; } if (write(dstfd, buf, to_write) < 0) return (-1); if (dstfd == srcfd) { if (lseek(srcfd, srcoff, SEEK_SET) < 0) return (-1); dstoff += to_write; } size -= to_write; } return (0); } /* * _compress: * Gzip logfile. * XXX: use built-in gzip (auditd uses zlib) */ static void _compress(const char *rpath) { pid_t pid; if ( (pid = fork()) == 0) { execl("/usr/bin/gzip", "gzip", "-f" , rpath, NULL); exit(0); } waitpid(pid, NULL, 0); } /* * _get_logset_name() */ static void _get_logset_name(ATTRCON *context, struct attrargs_ret *args) { CLASSIC_CTX *cc; cc = GET_CLASSIC_CTX(context); args->data = cc->logset_name; args->size = strlen(cc->logset_name); } /* * _freeze(): * Freeze logfile status; return 0 on success and * -1 on error (the error message is logged). */ static int _freeze(ATTRCON *context) { CLASSIC_CTX *cc; cc = GET_CLASSIC_CTX(context); if (stat(cc->logset_name, &cc->st) < 0) { log_err(ATTR_CLASSIC "Can't stat '%s': %s.", cc->logset_name, strerror(errno)); return (-1); } return (0); } /* * _info(): * Return logset information coded as a string: * "classic * name * offset * size * uid * gid * type * perms * last_access