/* $CoreSDI: ia.c,v 1.17 2001/10/10 00:30:11 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. */ /* * Information Accessing commands * Author: Claudio Castiglia */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__FreeBSD__) && (__FreeBSD_version >= 500035) #include #endif #include "sysdep.h" #include "packet.h" #include "version.h" #include "audit.h" #include "audconf.h" #include "commands.h" #include "log.h" #include "resource.h" #include "modtypes.h" #include "modules.h" #include "ia_list.h" #include "ia_perm.h" #include "iaargs.h" extern AUDITD_OPTIONS options; extern void send_error(PACKET *, const char *, ...); extern void internal_error(PACKET *); extern void send_string_list(PACKET *, int, const char **); /* * _sync_attrs(): * Synchronize attributes status. * Before calling this function you MUST lock IA module; * After this function returns you MUST unlock IA module. */ static int _sync_attrs(LOGSET_INFO *li, const char *logset_name) { ATTR *at; log_debug("Synchronizing attributes."); for (at = li->attr; at != NULL; at = at->next) if (at->a_proc(ATTR_FREEZE, at->atcon, NULL) < 0) { log_debug("Synchronization aborted."); return (-1); } return (0); } /* * _lock(): * Locks ia system; returns 0 in success and -1 on error (the error * is loggued in the server host and into the other side). */ static int _lock(SESSION *s, char *logset_name) { if (s->s_iaproc(IA_LOCK, s->iacon, logset_name) < 0) { send_error(s->s_packet, "Can't lock '%s': %s.", logset_name, strerror(errno)); return (-1); } return (0); } /* * _unlock(): * Unlocks ia system; returns 0 in success and -1 on error (the error * is loggued in the server host and into the other side). */ static int _unlock(SESSION *s, char *logset_name) { if (s->s_iaproc(IA_UNLOCK, s->iacon, logset_name) < 0) { send_error(s->s_packet, "Can't unlock '%s': %s.", logset_name, strerror(errno)); return (-1); } return (0); } /* * _ia_loaded(): * Return a ero value if IA module loaded; * If the logset does not exits, an error message is sent to the * client and -1 is returned. */ static int _ia_loaded(SESSION *s) { if (s->iacon != NULL) { if (s->s_logset != NULL) return (0); } send_error(s->s_packet, "IA module not set."); return (-1); } /* * ia_get_module_list(): * Send IA module list to the client. */ void ia_get_module_list(SESSION *session) { log_debug("Sending IA module list."); packet_put_int32(session->s_packet, CMD_OK); send_string_list(session->s_packet, options.ia_modules, (const char **) options.ia_list); log_cmd(session->s_peername, "Ok", "GET MODULE LIST"); } /* * ia_set_module(): * Set specified IA module: * Load IA module and its associated LOGSET_INFO list. * * XXX: check permissions on AllowedIAModules resource */ void ia_set_module(SESSION *s) { char module_name[MAXPATHLEN]; int i; IACON *iacon; RAW_LOGSET *rawset, *r; LOGSET_INFO *logset, *l; unsigned int generic_perms; /* Get IA module name and search it on server ia modules list */ packet_get_string(s->s_packet, module_name, sizeof(module_name)); for (i = 0; i < options.ia_modules; i++) if (!strcmp(options.ia_list[i], module_name)) break; if (i == options.ia_modules) { log_cmd(s->s_peername, "Error: Invalid module name", "SET '%s' IA MODULE", module_name); send_error(s->s_packet, ""); return; } /* Load module */ iacon = load_ia(options.ia_list[i]); if (iacon == NULL) { log_cmd(s->s_peername, "Error: Can't load module", "SET '%s' IA MODULE", options.ia_list[i]); send_error(s->s_packet, "Can't set '%s'.", options.ia_list[i]); return; } /* Generate LOGSET_INFO list based on RAW_LOGSET list */ rawset = (RAW_LOGSET *) iacon->logset; logset = l = NULL; generic_perms = PERM_INVALID; for (r = rawset; r != NULL; r = r->next) { if (create_logset_info(l, r, s, &generic_perms, &l) < 0) { log_debug("Can't initialize IA module: %s: %s.", options.ia_list[i], r->cmd->data); log_cmd(s->s_peername, "Error", "SET '%s' IA MODULE", options.ia_list[i]); internal_error(s->s_packet); release_logset_info(logset); release_raw_logset(rawset); release_module((void *) iacon); return; } if (logset == NULL) logset = l; } /* Release previous ia module and set the new one */ release_raw_logset(rawset); iacon->logset = logset; release_ia(s->iacon); s->iacon = iacon; packet_put_int32(s->s_packet, CMD_OK); log_cmd(s->s_peername, "Ok", "SET '%s' IA MODULE", options.ia_list[i]); } /* * ia_get_list(): * If client has LIST permissions, send logset list. */ void ia_get_list(SESSION *s) { int i; LOGSET_INFO *l; log_debug("Sending logset list."); /* Send Ok to indicate command accepted */ packet_put_int32(s->s_packet, CMD_OK); /* Send first name of each logset (with LIST permissions) */ for (l = s->s_logset; l != NULL; l = l->next) { for (i = 0; i < l->names; i++) if (l->names_str[i] != '\0') break; if (i < l->names && (l->perms & PERM_LIST) == PERM_LIST) packet_put_string(s->s_packet, l->names_str[i]); } /* End of name list */ packet_put_string(s->s_packet, ""); log_cmd(s->s_peername, "Ok", "GET LOGSET LIST"); } /* * ia_get_info(): * If client has INFO permissions, send logset info. */ void ia_get_info(SESSION *s) { char logset_name[MAXPATHLEN], info[LINE_MAX]; LOGSET_INFO *li; struct attrargs_ret info_args; ATTR *at; int status; log_debug("Sending logset information."); /* Get logset name */ packet_get_string(s->s_packet, logset_name, sizeof(logset_name)); if (_ia_loaded(s) < 0) { log_cmd(s->s_peername, "IA module not loaded", "GET INFO '%s'", logset_name); return; } li = find_logset_info(s->s_logset, logset_name); if (li == NULL) { log_cmd(s->s_peername, "Not found", "GET '%s' INFO", logset_name); send_error(s->s_packet, "%s: Not found.", logset_name); return; } /* Test INFO perms */ if (!((li->perms & PERM_INFO) == PERM_INFO)) { log_cmd(s->s_peername, strerror(EACCES), "GET '%s' INFO", logset_name); send_error(s->s_packet, "%s: %s", logset_name, strerror(EACCES)); return; } /* Synchronize attributes */ if (_lock(s, logset_name) < 0) { log_cmd(s->s_peername, strerror(errno), "GET '%s' INFO", logset_name); return; } status = _sync_attrs(li, logset_name); if (_unlock(s, logset_name) < 0) { log_cmd(s->s_peername, strerror(errno), "GET '%s' INFO", logset_name); return; } if (status < 0) { internal_error(s->s_packet); return; } /* Accept command and send each attribute information */ packet_put_int32(s->s_packet, CMD_OK); for (at = li->attr; at != NULL; at = at->next) { info_args.data = info; info_args.size = sizeof(info); at->a_proc(ATTR_INFO, at->atcon, &info_args); if (info_args.size) packet_put_string(s->s_packet, info); } /* End of string list */ packet_put_string(s->s_packet, ""); log_cmd(s->s_peername, "Ok", "GET '%s' INFO", logset_name); } /* * ia_get(): * Send logset to the client (information and logs). */ void ia_get(SESSION *s) { char logset_name[MAXPATHLEN], info[LINE_MAX]; LOGSET_INFO *li; struct attrargs_ret get_args; ATTR *at; int status; /* Get logset name */ packet_get_string(s->s_packet, logset_name, sizeof(logset_name)); log_debug("Sending logset '%s'.", logset_name); if (_ia_loaded(s) < 0) { log_cmd(s->s_peername, "IA module not loaded", "GET '%s'", logset_name); return; } li = find_logset_info(s->s_logset, logset_name); if (li == NULL) { log_cmd(s->s_peername, "Not found", "GET '%s'", logset_name); send_error(s->s_packet, "%s: Not found.", logset_name); return; } /* Test GET perms */ if (!((li->perms & PERM_GET) == PERM_GET)) { log_cmd(s->s_peername, strerror(EACCES), "GET '%s'", logset_name); send_error(s->s_packet, "%s: %s.", logset_name, strerror(EACCES)); return; } /* Synchronize attributes */ if (_lock(s, logset_name) < 0) { log_cmd(s->s_peername, strerror(errno), "GET '%s'", logset_name); return; } status = _sync_attrs(li, logset_name); if (_unlock(s, logset_name) < 0) { log_cmd(s->s_peername, strerror(errno), "GET '%s'", logset_name); return; } if (status < 0) { internal_error(s->s_packet); return; } /* Accept command and send information */ packet_put_int32(s->s_packet, CMD_OK); for (at = li->attr; at != NULL; at = at->next) { get_args.data = info; get_args.size = sizeof(info); at->a_proc(ATTR_INFO, at->atcon, &get_args); if (get_args.size) packet_put_string(s->s_packet, info); } /* End of info string list */ packet_put_string(s->s_packet, ""); /* Send logs */ for (at = li->attr; at != NULL; at = at->next) { if ( (status = at->a_proc(ATTR_GET, at->atcon, NULL)) != 0) { log_cmd(s->s_peername, "Error", "GET '%s'", logset_name); internal_error(s->s_packet); return; } } /* End of log list */ packet_put_string(s->s_packet, ""); packet_put_int32(s->s_packet, CMD_OK); log_cmd(s->s_peername, "Ok", "GET '%s'", logset_name); } /* * ia_zap(): * Zap logset. */ void ia_zap(SESSION *s) { char logset_name[MAXPATHLEN]; LOGSET_INFO *li; ATTR *at; int status; /* Get logset name */ packet_get_string(s->s_packet, logset_name, sizeof(logset_name)); log_debug("Zapping logset '%s'.", logset_name); if (_ia_loaded(s) < 0) { log_cmd(s->s_peername, "IA module not loaded", "ZAP '%s'", logset_name); return; } li = find_logset_info(s->s_logset, logset_name); if (li == NULL) { log_cmd(s->s_peername, "Not found", "ZAP '%s'", logset_name); send_error(s->s_packet, "%s: Not found.", logset_name); return; } /* Test ZAP perms */ if (!((li->perms & PERM_ZAP) == PERM_ZAP)) { log_cmd(s->s_peername, strerror(EACCES), "ZAP '%s'", logset_name); send_error(s->s_packet, "%s: %s.", logset_name, strerror(EACCES)); return; } /* Sync attributes stat */ if (_lock(s, logset_name) < 0) { log_cmd(s->s_peername, strerror(errno), "ZAP '%s'", logset_name); return; } status = _sync_attrs(li, logset_name); if (_unlock(s, logset_name) < 0) { log_cmd(s->s_peername, strerror(errno), "ZAP '%s'", logset_name); return; } if (status < 0) { internal_error(s->s_packet); return; } /* First zap step */ for (at = li->attr; at != NULL; at = at->next) { status = at->a_proc(ATTR_ZAP, at->atcon, (void *) 0); if (status < 0) { log_cmd(s->s_peername, "Error", "ZAP '%s'", logset_name); internal_error(s->s_packet); return; } } /* Sync attributes stat and last zap step */ if (_lock(s, logset_name) < 0) { /* Can't complete command */ log_cmd(s->s_peername, strerror(errno), "ZAP '%s'", logset_name); fatal(EX_SOFTWARE, "Command ZAP '%s' aborted.", logset_name); /* NOTREACHED */ } _sync_attrs(li, logset_name); for (at = li->attr; at != NULL; at = at->next) { status = at->a_proc(ATTR_ZAP, at->atcon, (void *) 1); if (status < 0) { if (_unlock(s, logset_name)) { log_cmd(s->s_peername, strerror(errno), "ZAP '%s'", logset_name); return; } log_cmd(s->s_peername, "Error" , "ZAP '%s'", logset_name); internal_error(s->s_packet); return; } } if (_unlock(s, logset_name) < 0) { log_cmd(s->s_peername, strerror(errno), "ZAP '%s'", logset_name); } else { log_cmd(s->s_peername, "Ok", "ZAP '%s'", logset_name); packet_put_int32(s->s_packet, CMD_OK); } } /* * ia_rotate(): * Rotate logset. */ void ia_rotate(SESSION *s) { char logset_name[MAXPATHLEN]; LOGSET_INFO *li; ATTR *at; int status; /* Get logset name */ packet_get_string(s->s_packet, logset_name, sizeof(logset_name)); log_debug("Rotating logset '%s'.", logset_name); if (_ia_loaded(s) < 0) { log_cmd(s->s_peername, "IA module not loaded", "ROTATE '%s'", logset_name); return; } li = find_logset_info(s->s_logset, logset_name); if (li == NULL) { log_cmd(s->s_peername, "Not found", "ROTATE '%s'", logset_name); send_error(s->s_packet, "%s: Not found.", logset_name); return; } /* Test ROTATE perms */ if (!((li->perms & PERM_ROTATE) == PERM_ROTATE)) { log_cmd(s->s_peername, strerror(EACCES), "ROTATE '%s'", logset_name); send_error(s->s_packet, "%s: %s.", logset_name, strerror(EACCES)); return; } /* Sync attributes stat */ if (_lock(s, logset_name) < 0) { log_cmd(s->s_peername, strerror(errno), "ROTATE '%s'", logset_name); return; } status = _sync_attrs(li, logset_name); if (_unlock(s, logset_name) < 0) { log_cmd(s->s_peername, strerror(errno), "ROTATE '%s'", logset_name); return; } if (status < 0) { internal_error(s->s_packet); return; } /* First rotate step */ for (at = li->attr; at != NULL; at = at->next) { status = at->a_proc(ATTR_ROTATE, at->atcon, (void *) 0); if (status < 0) { log_cmd(s->s_peername, "Error", "ROTATE '%s'", logset_name); internal_error(s->s_packet); return; } } /* Sync attributes status and last rotate step */ if (_lock(s, logset_name) < 0) { /* Can't complete command */ log_cmd(s->s_peername, strerror(errno), "ROTATE '%s'", logset_name); fatal(EX_SOFTWARE, "Command ROTATE '%s' aborted.", logset_name); /* NOTREACHED */ } _sync_attrs(li, logset_name); for (at = li->attr; at != NULL; at = at->next) { status = at->a_proc(ATTR_ROTATE, at->atcon, (void *) 1); if (status < 0) { if (_unlock(s, logset_name) < 0) { log_cmd(s->s_peername, strerror(errno), "ROTATE '%s'", logset_name); return; } log_cmd(s->s_peername, "Error", "ROTATE '%s'", logset_name); internal_error(s->s_packet); return; } } s->s_iaproc(IA_UNLOCK, s->iacon, logset_name); if (_unlock(s, logset_name) < 0) { log_cmd(s->s_peername, strerror(errno), "ROTATE '%s'", logset_name); } else { log_cmd(s->s_peername, "Ok", "ROTATE '%s'", logset_name); packet_put_int32(s->s_packet, CMD_OK); } } /* * ia_sign(): * Sign a logset. */ void ia_sign(SESSION *s) { /* XXX */ log_cmd(s->s_peername, strerror(EOPNOTSUPP), "SIGN"); packet_put_int32(s->s_packet, CMD_ERROR); packet_put_string(s->s_packet, strerror(EOPNOTSUPP)); }