/** * @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 #include "sefs_internal.hh" #include #include #include #include #include /******************** 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; }