summaryrefslogtreecommitdiffstats
path: root/libsefs/src/query.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libsefs/src/query.cc')
-rw-r--r--libsefs/src/query.cc431
1 files changed, 431 insertions, 0 deletions
diff --git a/libsefs/src/query.cc b/libsefs/src/query.cc
new file mode 100644
index 0000000..64c4e6b
--- /dev/null
+++ b/libsefs/src/query.cc
@@ -0,0 +1,431 @@
+/**
+ * @file
+ * Implementation of the sefs_query class.
+ *
+ * @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
+ */
+
+#include <config.h>
+
+#include "sefs_internal.hh"
+
+#include <sefs/query.hh>
+#include <apol/util.h>
+#include <qpol/genfscon_query.h>
+
+#include <assert.h>
+#include <errno.h>
+
+/******************** public functions below ********************/
+
+sefs_query::sefs_query()
+{
+ _user = _role = _type = _range = NULL;
+ _path = _dev = NULL;
+ _objclass = QPOL_CLASS_ALL;
+ _indirect = _regex = _recursive = false;
+ _inode = 0;
+ _recompiled = false;
+ _reuser = _rerole = _retype = _rerange = _repath = _redev = NULL;
+}
+
+sefs_query::~sefs_query()
+{
+ free(_user);
+ free(_role);
+ free(_type);
+ free(_range);
+ free(_path);
+ free(_dev);
+ if (_recompiled)
+ {
+ regfree(_reuser);
+ free(_reuser);
+ regfree(_rerole);
+ free(_rerole);
+ regfree(_retype);
+ free(_retype);
+ regfree(_rerange);
+ free(_rerange);
+ regfree(_repath);
+ free(_repath);
+ regfree(_redev);
+ free(_redev);
+ }
+}
+
+void sefs_query::user(const char *name) throw(std::bad_alloc)
+{
+ if (name != _user)
+ {
+ free(_user);
+ _user = NULL;
+ if (name != NULL && *name != '\0' && (_user = strdup(name)) == NULL)
+ {
+ throw std::bad_alloc();
+ }
+ }
+}
+
+void sefs_query::role(const char *name) throw(std::bad_alloc)
+{
+ if (name != _role)
+ {
+ free(_role);
+ _role = NULL;
+ if (name != NULL && *name != '\0' && (_role = strdup(name)) == NULL)
+ {
+ throw std::bad_alloc();
+ }
+ }
+}
+
+void sefs_query::type(const char *name, bool indirect) throw(std::bad_alloc)
+{
+ if (name != _type)
+ {
+ free(_type);
+ _type = NULL;
+ if (name != NULL && *name != '\0')
+ {
+ if ((_type = strdup(name)) == NULL)
+ {
+ throw std::bad_alloc();
+ }
+ _indirect = indirect;
+ }
+ }
+}
+
+void sefs_query::range(const char *name, int match) throw(std::bad_alloc)
+{
+ if (name != _range)
+ {
+ free(_range);
+ _range = NULL;
+ if (name != NULL && *name != '\0')
+ {
+ if ((_range = strdup(name)) == NULL)
+ {
+ throw std::bad_alloc();
+ }
+ _rangeMatch = match;
+ }
+ }
+}
+
+void sefs_query::objectClass(uint32_t objclass)
+{
+ _objclass = objclass;
+}
+
+void sefs_query::objectClass(const char *name)
+{
+ if (name == NULL || *name == '\0' || strcmp(name, "any") == 0)
+ {
+ _objclass = QPOL_CLASS_ALL;
+ }
+ else
+ {
+ uint32_t o = apol_str_to_objclass(name);
+ if (o != QPOL_CLASS_ALL)
+ {
+ _objclass = o;
+ }
+ }
+}
+
+void sefs_query::path(const char *str) throw(std::bad_alloc)
+{
+ if (str != _path)
+ {
+ free(_path);
+ _path = NULL;
+ if (str != NULL && *str != '\0' && (_path = strdup(str)) == NULL)
+ {
+ throw std::bad_alloc();
+ }
+ }
+}
+
+void sefs_query::inode(ino64_t ino)
+{
+ _inode = ino;
+}
+
+void sefs_query::dev(const char *str) throw(std::bad_alloc)
+{
+ if (str != _dev)
+ {
+ free(_dev);
+ _dev = NULL;
+ if (str != NULL && *str != '\0' && (_dev = strdup(str)) == NULL)
+ {
+ throw std::bad_alloc();
+ }
+ }
+}
+
+void sefs_query::regex(bool r)
+{
+ _regex = r;
+}
+
+/******************** private functions below ********************/
+
+void sefs_query::compile() throw(std::bad_alloc, std::invalid_argument)
+{
+ if (_recompiled)
+ {
+ regfree(_reuser);
+ regfree(_rerole);
+ regfree(_retype);
+ regfree(_rerange);
+ regfree(_repath);
+ regfree(_redev);
+ }
+ else
+ {
+ if ((_reuser = static_cast < regex_t * >(malloc(sizeof(*_reuser)))) == NULL)
+ {
+ throw std::bad_alloc();
+ }
+ if ((_rerole = static_cast < regex_t * >(malloc(sizeof(*_rerole)))) == NULL)
+ {
+ throw std::bad_alloc();
+ }
+ if ((_retype = static_cast < regex_t * >(malloc(sizeof(*_retype)))) == NULL)
+ {
+ throw std::bad_alloc();
+ }
+ if ((_rerange = static_cast < regex_t * >(malloc(sizeof(*_rerange)))) == NULL)
+ {
+ throw std::bad_alloc();
+ }
+ if ((_repath = static_cast < regex_t * >(malloc(sizeof(*_repath)))) == NULL)
+ {
+ throw std::bad_alloc();
+ }
+ if ((_redev = static_cast < regex_t * >(malloc(sizeof(*_redev)))) == NULL)
+ {
+ throw std::bad_alloc();
+ }
+ }
+ char errbuf[1024] = { '\0' };
+ int regretv;
+ const char *s = (_user == NULL ? "" : _user);
+ if ((regretv = regcomp(_reuser, s, REG_EXTENDED | REG_NOSUB)))
+ {
+ regerror(regretv, _reuser, errbuf, 1024);
+ throw std::invalid_argument(errbuf);
+ }
+ s = (_role == NULL ? "" : _role);
+ if ((regretv = regcomp(_rerole, s, REG_EXTENDED | REG_NOSUB)))
+ {
+ regerror(regretv, _reuser, errbuf, 1024);
+ throw std::invalid_argument(errbuf);
+ }
+ s = (_type == NULL ? "" : _type);
+ if ((regretv = regcomp(_retype, s, REG_EXTENDED | REG_NOSUB)))
+ {
+ regerror(regretv, _reuser, errbuf, 1024);
+ throw std::invalid_argument(errbuf);
+ }
+ s = (_range == NULL ? "" : _range);
+ if ((regretv = regcomp(_rerange, s, REG_EXTENDED | REG_NOSUB)))
+ {
+ regerror(regretv, _reuser, errbuf, 1024);
+ throw std::invalid_argument(errbuf);
+ }
+ s = (_path == NULL ? "" : _path);
+ if ((regretv = regcomp(_repath, s, REG_EXTENDED | REG_NOSUB)))
+ {
+ regerror(regretv, _reuser, errbuf, 1024);
+ throw std::invalid_argument(errbuf);
+ }
+ s = (_dev == NULL ? "" : _dev);
+ if ((regretv = regcomp(_redev, s, REG_EXTENDED | REG_NOSUB)))
+ {
+ regerror(regretv, _reuser, errbuf, 1024);
+ throw std::invalid_argument(errbuf);
+ }
+ _recompiled = true;
+}
+
+/******************** C functions below ********************/
+
+sefs_query_t *sefs_query_create()
+{
+ return new sefs_query();
+}
+
+void sefs_query_destroy(sefs_query_t ** query)
+{
+ if (query != NULL && *query != NULL)
+ {
+ delete(*query);
+ *query = NULL;
+ }
+}
+
+int sefs_query_set_user(sefs_query_t * query, const char *name)
+{
+ if (query == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ try
+ {
+ query->user(name);
+ }
+ catch(...)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+int sefs_query_set_role(sefs_query_t * query, const char *name)
+{
+ if (query == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ try
+ {
+ query->role(name);
+ }
+ catch(...)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+int sefs_query_set_type(sefs_query_t * query, const char *name, bool indirect)
+{
+ if (query == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ try
+ {
+ query->type(name, indirect);
+ }
+ catch(...)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+int sefs_query_set_range(sefs_query_t * query, const char *range, int match)
+{
+ if (query == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ query->range(range, match);
+ return 0;
+}
+
+int sefs_query_set_object_class(sefs_query_t * query, uint32_t objclass)
+{
+ if (query == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ query->objectClass(objclass);
+ return 0;
+}
+
+int sefs_query_set_object_class_str(sefs_query_t * query, const char *name)
+{
+ if (query == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ query->objectClass(name);
+ return 0;
+}
+
+int sefs_query_set_path(sefs_query_t * query, const char *path)
+{
+ if (query == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ try
+ {
+ query->path(path);
+ }
+ catch(...)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+int sefs_query_set_inode(sefs_query_t * query, ino64_t inode)
+{
+ if (query == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ query->inode(inode);
+ return 0;
+}
+
+int sefs_query_set_dev(sefs_query_t * query, const char *dev)
+{
+ if (query == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ try
+ {
+ query->dev(dev);
+ }
+ catch(...)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+int sefs_query_set_regex(sefs_query_t * query, bool regex)
+{
+ if (query == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ query->regex(regex);
+ return 0;
+}