sysdb_selinux.c revision 7a1a56860993475d0025e7411547649abf09d32c
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke/*
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke SSSD
9eb6a481980d81a55898ba418fba72fc3c09d8c8Dominik Luecke
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke System Database - SELinux support
98890889ffb2e8f6f722b00e265a211f13b5a861Corneliu-Claudiu Prodescu
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke Copyright (C) Jan Zeleny <jzeleny@redhat.com> 2012
2eeec5240b424984e3ee26296da1eeab6c6d739eChristian Maeder
b72a390042c19e630cf221494b60c9df2a60d187Dominik Luecke This program is free software; you can redistribute it and/or modify
b72a390042c19e630cf221494b60c9df2a60d187Dominik Luecke it under the terms of the GNU General Public License as published by
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke the Free Software Foundation; either version 3 of the License, or
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke (at your option) any later version.
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder
2af38fde95f93562f2124ec615fba0e509c8202eDominik Luecke This program is distributed in the hope that it will be useful,
2af38fde95f93562f2124ec615fba0e509c8202eDominik Luecke but WITHOUT ANY WARRANTY; without even the implied warranty of
2af38fde95f93562f2124ec615fba0e509c8202eDominik Luecke MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
cf04ba46b9eb495d334466e24e082e391055ca7bDominik Luecke GNU General Public License for more details.
2af38fde95f93562f2124ec615fba0e509c8202eDominik Luecke
2af38fde95f93562f2124ec615fba0e509c8202eDominik Luecke You should have received a copy of the GNU General Public License
926b3c5491f1c608f5b79e2d8014d7a1385558c3Dominik Luecke along with this program. If not, see <http://www.gnu.org/licenses/>.
2af38fde95f93562f2124ec615fba0e509c8202eDominik Luecke*/
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke#include "util/sss_selinux.h"
da955132262baab309a50fdffe228c9efe68251dCui Jian#include "db/sysdb_selinux.h"
16e124196c6b204769042028c74f533509c9b5d3Christian Maeder#include "db/sysdb_private.h"
16e124196c6b204769042028c74f533509c9b5d3Christian Maeder
16e124196c6b204769042028c74f533509c9b5d3Christian Maeder/* Some generic routines */
16e124196c6b204769042028c74f533509c9b5d3Christian Maederenum selinux_entity_type {
16e124196c6b204769042028c74f533509c9b5d3Christian Maeder SELINUX_CONFIG,
16e124196c6b204769042028c74f533509c9b5d3Christian Maeder SELINUX_USER_MAP
16e124196c6b204769042028c74f533509c9b5d3Christian Maeder};
16e124196c6b204769042028c74f533509c9b5d3Christian Maeder
16e124196c6b204769042028c74f533509c9b5d3Christian Maederstatic errno_t
16e124196c6b204769042028c74f533509c9b5d3Christian Maedersysdb_add_selinux_entity(struct sysdb_ctx *sysdb,
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder struct ldb_dn *dn,
16e124196c6b204769042028c74f533509c9b5d3Christian Maeder const char *objectclass,
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke struct sysdb_attrs *attrs,
fcac596b16bb10f475066c323b9b1ca44db2b755Dominik Luecke time_t now)
fcac596b16bb10f475066c323b9b1ca44db2b755Dominik Luecke{
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke struct ldb_message *msg;
5b9f5c1b3592b99fc74d3438740ebcf9eb4c94beDominik Luecke TALLOC_CTX *tmp_ctx;
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke errno_t ret;
5b9f5c1b3592b99fc74d3438740ebcf9eb4c94beDominik Luecke
08056875f5f633ef432598d5245ea41c112d2178Dominik Luecke tmp_ctx = talloc_new(NULL);
fcac596b16bb10f475066c323b9b1ca44db2b755Dominik Luecke if (!tmp_ctx) {
fcac596b16bb10f475066c323b9b1ca44db2b755Dominik Luecke return ENOMEM;
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke }
da955132262baab309a50fdffe228c9efe68251dCui Jian
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder msg = ldb_msg_new(tmp_ctx);
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke if (!msg) {
16e124196c6b204769042028c74f533509c9b5d3Christian Maeder ret = ENOMEM;
16e124196c6b204769042028c74f533509c9b5d3Christian Maeder goto done;
16e124196c6b204769042028c74f533509c9b5d3Christian Maeder }
16e124196c6b204769042028c74f533509c9b5d3Christian Maeder
b72a390042c19e630cf221494b60c9df2a60d187Dominik Luecke ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS, objectclass);
fcac596b16bb10f475066c323b9b1ca44db2b755Dominik Luecke if (ret != EOK) {
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder DEBUG(SSSDBG_OP_FAILURE, ("Could not set map object class [%d]: %s\n",
08056875f5f633ef432598d5245ea41c112d2178Dominik Luecke ret, strerror(ret)));
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder return ret;
b72a390042c19e630cf221494b60c9df2a60d187Dominik Luecke }
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder
08056875f5f633ef432598d5245ea41c112d2178Dominik Luecke if (!now) {
08056875f5f633ef432598d5245ea41c112d2178Dominik Luecke now = time(NULL);
08056875f5f633ef432598d5245ea41c112d2178Dominik Luecke }
da955132262baab309a50fdffe228c9efe68251dCui Jian
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder ret = sysdb_attrs_add_time_t(attrs, SYSDB_CREATE_TIME, now);
548f3850942936a8c6021185c8391dfcd3b03018Dominik Luecke if (ret) goto done;
548f3850942936a8c6021185c8391dfcd3b03018Dominik Luecke
0b53895114b00141ec17ffdc7e26acded4487328Christian Maeder msg->dn = dn;
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder msg->elements = attrs->a;
548f3850942936a8c6021185c8391dfcd3b03018Dominik Luecke msg->num_elements = attrs->num;
548f3850942936a8c6021185c8391dfcd3b03018Dominik Luecke
548f3850942936a8c6021185c8391dfcd3b03018Dominik Luecke ret = ldb_add(sysdb->ldb, msg);
548f3850942936a8c6021185c8391dfcd3b03018Dominik Luecke ret = sysdb_error_to_errno(ret);
548f3850942936a8c6021185c8391dfcd3b03018Dominik Luecke
548f3850942936a8c6021185c8391dfcd3b03018Dominik Lueckedone:
5b2e9f4673599e1bc6e18a43ad615da28305b8e1Christian Maeder if (ret) {
548f3850942936a8c6021185c8391dfcd3b03018Dominik Luecke DEBUG(SSSDBG_TRACE_LIBS, ("Error: %d (%s)\n", ret, strerror(ret)));
08056875f5f633ef432598d5245ea41c112d2178Dominik Luecke }
08056875f5f633ef432598d5245ea41c112d2178Dominik Luecke talloc_zfree(tmp_ctx);
08056875f5f633ef432598d5245ea41c112d2178Dominik Luecke return ret;
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder}
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder
08056875f5f633ef432598d5245ea41c112d2178Dominik Lueckestatic errno_t sysdb_store_selinux_entity(struct sysdb_ctx *sysdb,
08056875f5f633ef432598d5245ea41c112d2178Dominik Luecke struct sss_domain_info *domain,
08056875f5f633ef432598d5245ea41c112d2178Dominik Luecke struct sysdb_attrs *attrs,
a23e572c8f957cc051a1b0831abd6fe9380d45c7Christian Maeder enum selinux_entity_type type)
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder{
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder TALLOC_CTX *tmp_ctx;
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder bool in_transaction = false;
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder const char *objectclass = NULL;
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder const char *name;
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder char *clean_name;
fcac596b16bb10f475066c323b9b1ca44db2b755Dominik Luecke struct ldb_dn *dn = NULL;
fcac596b16bb10f475066c323b9b1ca44db2b755Dominik Luecke errno_t sret = EOK;
fcac596b16bb10f475066c323b9b1ca44db2b755Dominik Luecke errno_t ret;
0859769b65851f4c06d6d32fac084b0f4db56c94Christian Maeder time_t now;
da955132262baab309a50fdffe228c9efe68251dCui Jian
4df63f7187b1ba16cbe5c781db187a42f2f49579Dominik Luecke tmp_ctx = talloc_new(NULL);
b694e4b3f771a2f32042c9c505dd698bde969558Dominik Luecke if (!tmp_ctx) {
5b9f5c1b3592b99fc74d3438740ebcf9eb4c94beDominik Luecke return ENOMEM;
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder }
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder switch (type) {
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder case SELINUX_USER_MAP:
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder objectclass = SYSDB_SELINUX_USERMAP_CLASS;
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke ret = sysdb_attrs_get_string(attrs, SYSDB_NAME, &name);
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke if (ret != EOK) {
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke goto done;
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke }
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder ret = sysdb_dn_sanitize(tmp_ctx, name, &clean_name);
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke if (ret != EOK) {
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder goto done;
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder }
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_SEUSERMAP,
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder clean_name, domain->name);
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder break;
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder case SELINUX_CONFIG:
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder objectclass = SYSDB_SELINUX_CLASS;
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_SELINUX_BASE,
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder domain->name);
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder break;
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder }
a7be28e157e9ceeec73a8fd0e642c36ea29d4218Christian Maeder
0b53895114b00141ec17ffdc7e26acded4487328Christian Maeder if (type != SELINUX_CONFIG && type != SELINUX_USER_MAP) {
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder DEBUG(SSSDBG_CRIT_FAILURE, ("Bad SELinux entity type: [%d]\n", type));
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder ret = EINVAL;
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder goto done;
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder }
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder if (!dn) {
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder ret = ENOMEM;
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder goto done;
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder }
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder ret = sysdb_transaction_start(sysdb);
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder if (ret != EOK) {
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n"));
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder goto done;
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder }
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder in_transaction = true;
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder now = time(NULL);
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder if (ret) goto done;
202df46772cac2ee2e8627ba196a5faebb6f9a05Christian Maeder
ret = sysdb_add_selinux_entity(sysdb, dn, objectclass, attrs, now);
if (ret != EOK) {
goto done;
}
ret = sysdb_set_entry_attr(sysdb, dn, attrs, SYSDB_MOD_REP);
if (ret != EOK) {
goto done;
}
ret = sysdb_transaction_commit(sysdb);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
goto done;
}
in_transaction = false;
done:
if (in_transaction) {
sret = sysdb_transaction_cancel(sysdb);
if (sret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n"));
}
}
if (ret) {
DEBUG(SSSDBG_MINOR_FAILURE, ("Error: %d (%s)\n", ret, strerror(ret)));
}
talloc_zfree(tmp_ctx);
return ret;
}
errno_t sysdb_store_selinux_usermap(struct sysdb_ctx *sysdb,
struct sss_domain_info *domain,
struct sysdb_attrs *attrs)
{
return sysdb_store_selinux_entity(sysdb, domain, attrs, SELINUX_USER_MAP);
}
errno_t sysdb_store_selinux_config(struct sysdb_ctx *sysdb,
struct sss_domain_info *domain,
const char *default_user,
const char *order)
{
errno_t ret;
struct sysdb_attrs *attrs;
attrs = talloc_zero(NULL, struct sysdb_attrs);
if (attrs == NULL) {
return ENOMEM;
}
if (!order) {
DEBUG(SSSDBG_CRIT_FAILURE, ("The SELinux order is missing\n"));
return EINVAL;
}
if (default_user) {
ret = sysdb_attrs_add_string(attrs, SYSDB_SELINUX_DEFAULT_USER,
default_user);
if (ret != EOK) {
goto done;
}
}
ret = sysdb_attrs_add_string(attrs, SYSDB_SELINUX_DEFAULT_ORDER,
order);
if (ret != EOK) {
goto done;
}
ret = sysdb_store_selinux_entity(sysdb, domain, attrs, SELINUX_CONFIG);
done:
talloc_free(attrs);
return ret;
}
errno_t sysdb_delete_usermaps(struct sysdb_ctx *sysdb,
struct sss_domain_info *domain)
{
struct ldb_dn *dn = NULL;
errno_t ret;
dn = ldb_dn_new_fmt(sysdb, sysdb->ldb,
SYSDB_TMPL_SELINUX_BASE, domain->name);
if (!dn) return ENOMEM;
ret = sysdb_delete_recursive(sysdb, dn, true);
talloc_free(dn);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, ("sysdb_delete_recursive failed.\n"));
return ret;
}
return EOK;
}
/* --- SYSDB SELinux search routines --- */
errno_t
sysdb_get_selinux_usermaps(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *sysdb,
struct sss_domain_info *domain,
const char **attrs,
size_t *count,
struct ldb_message ***messages)
{
errno_t ret;
char *filter;
struct ldb_dn *basedn;
basedn = ldb_dn_new_fmt(mem_ctx, sysdb_ctx_get_ldb(sysdb),
SYSDB_TMPL_SELINUX_BASE, domain->name);
if (!basedn) {
return ENOMEM;
}
filter = talloc_asprintf(mem_ctx, "(%s=%s)",
SYSDB_OBJECTCLASS, SYSDB_SELINUX_USERMAP_CLASS);
if (filter == NULL) {
talloc_free(basedn);
return ENOMEM;
}
ret = sysdb_search_entry(mem_ctx, sysdb, basedn, LDB_SCOPE_SUBTREE, filter,
attrs, count, messages);
talloc_free(basedn);
talloc_free(filter);
if (ret == ENOENT) {
*count = 0;
*messages = NULL;
} else if (ret) {
return ret;
}
return EOK;
}
errno_t sysdb_search_selinux_config(TALLOC_CTX *mem_ctx,
struct sysdb_ctx *sysdb,
struct sss_domain_info *domain,
const char **attrs,
struct ldb_message **_config)
{
TALLOC_CTX *tmp_ctx;
const char *def_attrs[] = { SYSDB_SELINUX_DEFAULT_USER,
SYSDB_SELINUX_DEFAULT_ORDER,
NULL };
struct ldb_message **msgs;
size_t msgs_count;
struct ldb_dn *basedn;
errno_t ret;
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) {
return ENOMEM;
}
basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
SYSDB_TMPL_SELINUX_BASE, domain->name);
if (!basedn) {
ret = ENOMEM;
goto done;
}
ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_BASE, NULL,
attrs?attrs:def_attrs, &msgs_count, &msgs);
if (ret) {
goto done;
}
*_config = talloc_steal(mem_ctx, msgs[0]);
done:
if (ret == ENOENT) {
DEBUG(SSSDBG_TRACE_FUNC, ("No SELinux root entry found\n"));
} else if (ret) {
DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
}
talloc_free(tmp_ctx);
return ret;
}