/** * @file * Defines the public interface for the file context list abstract * object. A user must call a constructor for one of sefs_fcfile_t, * sefs_db_t, or sefs_filesystem_t to create a sefs_fclist_t object. * * @author Jeremy A. Mowery jmowery@tresys.com * @author Jason Tang jtang@tresys.com * * Copyright (C) 2007 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef SEFS_FCLIST_H #define SEFS_FCLIST_H #include #include #ifdef __cplusplus extern "C" { #endif #include #include #ifndef __cplusplus #include #endif #include #define SEFS_MSG_ERR 1 /*!< Message describes a fatal error. */ #define SEFS_MSG_WARN 2 /*!< Message is issued as a warning but does not represent a fatal error. */ #define SEFS_MSG_INFO 3 /*!< Message is issued for inormational reasons and does not represent an atypical state. */ struct sefs_fclist; typedef void (*sefs_callback_fn_t) (void *varg, const struct sefs_fclist * fclist, int level, const char *fmt, va_list argp); /** * Possible types of fclist for use with sefs_fclist_get_data(). */ typedef enum sefs_fclist_type { SEFS_FCLIST_TYPE_NONE = 0, /*!< Not an actual type, used for error conditions */ SEFS_FCLIST_TYPE_FILESYSTEM, /*!< get_data returns sefs_filesystem_t, a representation of a file system */ SEFS_FCLIST_TYPE_FCFILE, /*!< get_data returns sefs_fcfile_t, a representation of a collection of file_context files */ SEFS_FCLIST_TYPE_DB /*!< get_data returns sefs_db_t, a representation of a database of file system contexts */ } sefs_fclist_type_e; /** * Invoke a sefs_fclist_t's callback for an error, passing it a format * string and arguments. */ #define SEFS_ERR(fclist, format, ...) sefs_fclist_handleMsg(fclist, SEFS_MSG_ERR, format, __VA_ARGS__) /** * Invoke a sefs_fclist_t's callback for a warning, passing it a * format string and arguments. */ #define SEFS_WARN(fclist, format, ...) sefs_fclist_handleMsg(fclist, SEFS_MSG_WARN, format, __VA_ARGS__) /** * Invoke a sefs_fclist's callback for an informational message, * passing it a format string and arguments. */ #define SEFS_INFO(fclist, format, ...) sefs_fclist_handleMsg(fclist, SEFS_MSG_INFO, format, __VA_ARGS__) extern void sefs_fclist_handleMsg(const struct sefs_fclist *fclist, int level, const char *fmt, ...); __attribute__ ((format(printf, 3, 4))) void sefs_fclist_handleMsg(const struct sefs_fclist *fclist, int level, const char *fmt, ...); #ifdef __cplusplus } #include struct apol_bst; struct context_node; #define SEFS_MAP_FUNC_DEFINED /** * Function invoked upon each matching file context entry during a query. */ typedef int (*sefs_fclist_map_fn_t) (sefs_fclist *, const sefs_entry *, void *); /** * An abstract class the represents a list of file contexts. Contexts * may be read from a filesystem, inferred from a file_contexts file, * or read from a database. */ class sefs_fclist { #ifndef SWIG_FRIENDS friend void sefs_fclist_handleMsg(const sefs_fclist * fclist, int level, const char *fmt, ...); friend class sefs_entry; #endif public: virtual ~sefs_fclist(); /** * Perform a sefs query on the given file context list object, * and then invoke a callback upon each matching entry. * Mapping occurs in the order of entries as specified by the * file context list. * @param query Query object containing search parameters. If * NULL, invoke the callback on all entries. * @param fn Function to invoke upon matching entries. This * function will be called with three parameters: a pointer to * this fclist, pointer to a matching entry, and an arbitrary * data pointer. It should return a non-negative value upon * success, negative value upon error and to abort the * mapping. Be aware that the entry may go out of scope upon * conclusion of runQueryMap(), so \a fn will need to clone * the entry if it needs it later. *

* This function must not throw any exceptions. Doing * so will most likely corrupt fclist's internal state. * Instead, return a negative value to abort processing. * @param data Arbitrary pointer to be passed into \a fn as a * third parameter. * @return Last value returned by fn() (i.e., >= on success, < * 0 on failure). If the fclist has no entries then return 0. * @exception std::runtime_error Error while reading contexts * from the fclist. * @exception std::invalid_argument One or more query arguments * is invalid. */ virtual int runQueryMap(sefs_query * query, sefs_fclist_map_fn_t fn, void *data) throw(std::runtime_error, std::invalid_argument) = 0; /** * Perform a sefs query on the given file context list object * and return a list of matching entries. * @param query Query object containing search parameters. If * NULL, return all contexts. * @return A newly allocated unsorted vector (of class * sefs_entry *) containing all entries matching the query. * Do not modify the returned entries. Note that the vector * may be empty. The caller is responsible for calling * apol_vector_destroy() on the returned vector. * @exception std::bad_alloc Out of memory. * @exception std::runtime_error Error while reading contexts * from the fclist. * @exception std::invalid_argument One or more query arguments * is invalid. */ apol_vector_t *runQuery(sefs_query * query) throw(std::bad_alloc, std::runtime_error, std::invalid_argument); /** * Determine if the contexts in the fclist contain MLS fields. * @return \a true if MLS fields are present, \a false if not * or undeterminable. */ virtual bool isMLS() const = 0; /** * Associate a policy with the fclist. This is needed to * resolve attributes and MLS ranges in queries. If a policy * is already associated, then calling this function removes * that previous association. * @param policy Policy to associate with \a fclist. If NULL, * remove any policy association. While \a policy is * associated with \a fclist the caller should not destroy \a * policy. * @see sefs_query_set_type() * @see sefs_query_set_range() */ void associatePolicy(apol_policy_t * new_policy); /** * Return the policy currently associated with this fclist. * Do not destroy the policy without first unassociating it * (via call to sefs_fclist::associatePolicy(NULL)). * @return Currently associated policy, or NULL if none is * set. */ apol_policy_t *associatePolicy() const; /** * Get the type of fclist object represented by \a fclist. * @return The type of fclist object or SEFS_FCLIST_TYPE_NONE * on error. */ sefs_fclist_type_e fclist_type() const; protected: sefs_fclist(sefs_fclist_type_e type, sefs_callback_fn_t callback, void *varg) throw(std::bad_alloc); /** * Given the parts of a context, return a context node (which * would contain an apol_context_t). If the context already * exists, then a pointer to the existing one is returned. * * @param user User component of the context. The string will * be duplicated. * @param role Role component of the context. The string will * be duplicated. * @param type Type component of the context. The string will * be duplicated. * @param range Range component of the context. The string * will be duplicated, or NULL if no range exists. * * @return A context node. Do not free() it. */ struct sefs_context_node *getContext(const char *user, const char *role, const char *type, const char *range) throw(std::bad_alloc); /** * Given a SELinux security context, return a context node * (which would contain an apol_context_t). If the context * already exists, then a pointer to the existing one is * returned. * * @param scon Security context from which to obtain a node. * * @return A context node. Do not free() it. */ struct sefs_context_node *getContext(const security_context_t scon) throw(std::bad_alloc); apol_policy_t *policy; struct apol_bst *user_tree, *role_tree, *type_tree, *range_tree, *path_tree; struct apol_bst *dev_tree; struct apol_bst *context_tree; private: /** * Write a message to the callback stored within a fclist * error handler. If the msg_callback field is empty, then * the default message callback will be used. * @param level Severity of message, one of SEFS_MSG_*. * @param fmt Format string to print, using syntax of * printf(3). */ void handleMsg(int level, const char *fmt, va_list va_args) const; sefs_callback_fn_t _callback; void *_varg; sefs_fclist_type_e _fclist_type; }; extern "C" { #endif //we do not want to wrap two copies of everything so have SWIG ignore //the compatibility section. #ifndef SWIG typedef struct sefs_fclist sefs_fclist_t; #ifndef SEFS_MAP_FUNC_DEFINED struct sefs_fclist; struct sefs_entry; typedef int (*sefs_fclist_map_fn_t) (struct sefs_fclist *, const struct sefs_entry *, void *); #endif /** * Deallocate all memory associated with the referenced fclist object, * and then set it to NULL. This function does nothing if the fclist * object is already NULL. * @param Reference to a fclist object to destroy. */ extern void sefs_fclist_destroy(sefs_fclist_t ** fclist); /** * Perform a sefs query on the given file context list object. * @see sefs_fclist::runQueryMap() */ extern int sefs_fclist_run_query_map(sefs_fclist_t * fclist, sefs_query_t * query, sefs_fclist_map_fn_t fn, void *data); /** * Perform a sefs query on the given file context list object. * @see sefs_fclist::runQuery() */ extern apol_vector_t *sefs_fclist_run_query(sefs_fclist_t * fclist, sefs_query_t * query); /** * Determine if the contexts in the fclist contain MLS fields. * @see sefs_fclist::isMLS() */ extern bool sefs_fclist_get_is_mls(const sefs_fclist_t * fclist); /** * Associate a policy with the fclist. * @see sefs_fclist::associatePolicy() * @see sefs_query_set_type() * @see sefs_query_set_range() */ extern void sefs_fclist_associate_policy(sefs_fclist_t * fclist, apol_policy_t * policy); /** * Get the type of fclist object represented by \a fclist. * @see sefs_fclist::fclist_type() */ extern sefs_fclist_type_e sefs_fclist_get_fclist_type(const sefs_fclist_t * fclist); #endif /* SWIG */ #ifdef __cplusplus } #endif #endif /* SEFS_FCLIST_H */