diff options
author | Pavel Březina <pbrezina@redhat.com> | 2015-12-16 14:42:04 +0100 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2016-01-19 14:33:04 +0100 |
commit | 68abbe716bed7c8d6790d9bec168ef44469306a1 (patch) | |
tree | 85066d550de84703072d0611627de5c7915d53c7 /src | |
parent | e9ae5cd285dcc8fa232e16f9c7a29f18537272f2 (diff) | |
download | sssd-68abbe716bed7c8d6790d9bec168ef44469306a1.tar.gz sssd-68abbe716bed7c8d6790d9bec168ef44469306a1.tar.xz sssd-68abbe716bed7c8d6790d9bec168ef44469306a1.zip |
SUDO: make sudo sysdb interface more reusable
Reviewed-by: Sumit Bose <sbose@redhat.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/db/sysdb.c | 98 | ||||
-rw-r--r-- | src/db/sysdb.h | 7 | ||||
-rw-r--r-- | src/db/sysdb_sudo.c | 286 | ||||
-rw-r--r-- | src/db/sysdb_sudo.h | 17 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_sudo.c | 121 | ||||
-rw-r--r-- | src/providers/ldap/sdap_sudo.c | 1 | ||||
-rw-r--r-- | src/providers/ldap/sdap_sudo_cache.c | 183 | ||||
-rw-r--r-- | src/providers/ldap/sdap_sudo_cache.h | 37 |
8 files changed, 354 insertions, 396 deletions
diff --git a/src/db/sysdb.c b/src/db/sysdb.c index a71364d7c..d4366a3c7 100644 --- a/src/db/sysdb.c +++ b/src/db/sysdb.c @@ -2013,3 +2013,101 @@ errno_t sysdb_msg2attrs(TALLOC_CTX *mem_ctx, size_t count, return EOK; } + +int sysdb_compare_usn(const char *a, const char *b) +{ + size_t len_a; + size_t len_b; + + if (a == NULL) { + return -1; + } + + if (b == NULL) { + return 1; + } + + len_a = strlen(a); + len_b = strlen(b); + + /* trim leading zeros */ + while (len_a > 0 && *a == '0') { + a++; + len_a--; + } + + while (len_b > 0 && *b == '0') { + b++; + len_b--; + } + + /* less digits means lower number */ + if (len_a < len_b) { + return -1; + } + + /* more digits means bigger number */ + if (len_a > len_b) { + return 1; + } + + /* now we can compare digits since alphabetical order is the same + * as numeric order */ + return strcmp(a, b); +} + +errno_t sysdb_get_highest_usn(TALLOC_CTX *mem_ctx, + struct sysdb_attrs **attrs, + size_t num_attrs, + char **_usn) +{ + const char *highest = NULL; + const char *current = NULL; + char *usn; + errno_t ret; + size_t i; + + if (num_attrs == 0 || attrs == NULL) { + goto done; + } + + for (i = 0; i < num_attrs; i++) { + ret = sysdb_attrs_get_string(attrs[i], SYSDB_USN, ¤t); + if (ret == ENOENT) { + /* USN value is not present, assuming zero. */ + current = "0"; + } else if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, "Failed to retrieve USN value " + "[%d]: %s\n", ret, sss_strerror(ret)); + + return ret; + } + + if (current == NULL) { + continue; + } + + if (highest == NULL) { + highest = current; + continue; + } + + if (sysdb_compare_usn(current, highest) > 0 ) { + highest = current; + } + } + +done: + if (highest == NULL) { + usn = talloc_strdup(mem_ctx, "0"); + } else { + usn = talloc_strdup(mem_ctx, highest); + } + + if (usn == NULL) { + return ENOMEM; + } + + *_usn = usn; + return EOK; +} diff --git a/src/db/sysdb.h b/src/db/sysdb.h index ad1bf75b7..2e797fd7f 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -386,6 +386,13 @@ errno_t sysdb_msg2attrs(TALLOC_CTX *mem_ctx, size_t count, struct ldb_message **msgs, struct sysdb_attrs ***attrs); +int sysdb_compare_usn(const char *a, const char *b); + +errno_t sysdb_get_highest_usn(TALLOC_CTX *mem_ctx, + struct sysdb_attrs **attrs, + size_t num_attrs, + char **_usn); + /* convert an ldb error into an errno error */ int sysdb_error_to_errno(int ldberr); diff --git a/src/db/sysdb_sudo.c b/src/db/sysdb_sudo.c index 784ac8af3..76116abac 100644 --- a/src/db/sysdb_sudo.c +++ b/src/db/sysdb_sudo.c @@ -27,6 +27,8 @@ #include "db/sysdb_private.h" #include "db/sysdb_sudo.h" +#define SUDO_ALL_FILTER "(" SYSDB_OBJECTCLASS "=" SYSDB_SUDO_CACHE_OC ")" + #define NULL_CHECK(val, rval, label) do { \ if (!val) { \ rval = ENOMEM; \ @@ -427,41 +429,6 @@ done: return ret; } -errno_t -sysdb_save_sudorule(struct sss_domain_info *domain, - const char *rule_name, - struct sysdb_attrs *attrs) -{ - errno_t ret; - - DEBUG(SSSDBG_TRACE_FUNC, "Adding sudo rule %s\n", rule_name); - - ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS, - SYSDB_SUDO_CACHE_OC); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Could not set rule object class [%d]: %s\n", - ret, strerror(ret)); - return ret; - } - - ret = sysdb_attrs_add_string(attrs, SYSDB_NAME, rule_name); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Could not set name attribute [%d]: %s\n", - ret, strerror(ret)); - return ret; - } - - ret = sysdb_store_custom(domain, rule_name, - SUDORULE_SUBDIR, attrs); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "sysdb_store_custom failed [%d]: %s\n", - ret, strerror(ret)); - return ret; - } - - return EOK; -} - static errno_t sysdb_sudo_set_refresh_time(struct sss_domain_info *domain, const char *attr_name, time_t value) @@ -615,6 +582,26 @@ errno_t sysdb_sudo_get_last_full_refresh(struct sss_domain_info *domain, /* ==================== Purge functions ==================== */ +static const char * +sysdb_sudo_get_rule_name(struct sysdb_attrs *rule) +{ + const char *name; + errno_t ret; + + ret = sysdb_attrs_get_string(rule, SYSDB_SUDO_CACHE_AT_CN, &name); + if (ret == ERANGE) { + DEBUG(SSSDBG_MINOR_FAILURE, "Warning: found rule that contains none " + "or multiple CN values. It will be skipped.\n"); + return NULL; + } else if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Unable to obtain rule name [%d]: %s\n", + ret, strerror(ret)); + return NULL; + } + + return name; +} + static errno_t sysdb_sudo_purge_all(struct sss_domain_info *domain) { struct ldb_dn *base_dn = NULL; @@ -627,6 +614,8 @@ static errno_t sysdb_sudo_purge_all(struct sss_domain_info *domain) base_dn = sysdb_custom_subtree_dn(tmp_ctx, domain, SUDORULE_SUBDIR); NULL_CHECK(base_dn, ret, done); + DEBUG(SSSDBG_TRACE_FUNC, "Deleting all cached sudo rules\n"); + ret = sysdb_delete_recursive(domain->sysdb, base_dn, true); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "sysdb_delete_recursive failed.\n"); @@ -639,42 +628,74 @@ done: return ret; } -errno_t sysdb_sudo_purge_byname(struct sss_domain_info *domain, - const char *name) +static errno_t +sysdb_sudo_purge_byname(struct sss_domain_info *domain, + const char *name) { DEBUG(SSSDBG_TRACE_INTERNAL, "Deleting sudo rule %s\n", name); return sysdb_delete_custom(domain, name, SUDORULE_SUBDIR); } -errno_t sysdb_sudo_purge_byfilter(struct sss_domain_info *domain, - const char *filter) +static errno_t +sysdb_sudo_purge_byrules(struct sss_domain_info *dom, + struct sysdb_attrs **rules, + size_t num_rules) +{ + const char *name; + errno_t ret; + size_t i; + + DEBUG(SSSDBG_TRACE_FUNC, "About to remove rules from sudo cache\n"); + + if (num_rules == 0 || rules == NULL) { + return EOK; + } + + for (i = 0; i < num_rules; i++) { + name = sysdb_sudo_get_rule_name(rules[i]); + if (name == NULL) { + continue; + } + + ret = sysdb_sudo_purge_byname(dom, name); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, "Failed to delete rule " + "%s [%d]: %s\n", name, ret, sss_strerror(ret)); + continue; + } + } + + return EOK; +} + +static errno_t +sysdb_sudo_purge_byfilter(struct sss_domain_info *domain, + const char *filter) { TALLOC_CTX *tmp_ctx; - size_t count; + struct sysdb_attrs **rules; struct ldb_message **msgs; - const char *name; - int i; + size_t count; errno_t ret; - errno_t sret; - bool in_transaction = false; const char *attrs[] = { SYSDB_OBJECTCLASS, SYSDB_NAME, SYSDB_SUDO_CACHE_AT_CN, NULL }; - /* just purge all if there's no filter */ - if (!filter) { + if (filter == NULL || strcmp(filter, SUDO_ALL_FILTER) == 0) { return sysdb_sudo_purge_all(domain); } tmp_ctx = talloc_new(NULL); - NULL_CHECK(tmp_ctx, ret, done); + if (tmp_ctx == NULL) { + ret = ENOMEM; + goto done; + } - /* match entries based on the filter and remove them one by one */ ret = sysdb_search_custom(tmp_ctx, domain, filter, SUDORULE_SUBDIR, attrs, &count, &msgs); - if (ret == ENOENT) { + if (ret == ENOENT || count == 0) { DEBUG(SSSDBG_TRACE_FUNC, "No rules matched\n"); ret = EOK; goto done; @@ -683,24 +704,165 @@ errno_t sysdb_sudo_purge_byfilter(struct sss_domain_info *domain, goto done; } + ret = sysdb_msg2attrs(tmp_ctx, count, msgs, &rules); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Unable to convert ldb message to " + "sysdb attrs [%d]: %s\n", ret, sss_strerror(ret)); + goto done; + } + + ret = sysdb_sudo_purge_byrules(domain, rules, count); + +done: + talloc_free(tmp_ctx); + return ret; +} + +errno_t sysdb_sudo_purge(struct sss_domain_info *domain, + const char *delete_filter, + struct sysdb_attrs **rules, + size_t num_rules) +{ + bool in_transaction = false; + errno_t sret; + errno_t ret; + ret = sysdb_transaction_start(domain->sysdb); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n"); - goto done; + return ret; } in_transaction = true; - for (i = 0; i < count; i++) { - name = ldb_msg_find_attr_as_string(msgs[i], SYSDB_NAME, NULL); - if (name == NULL) { - DEBUG(SSSDBG_OP_FAILURE, "A rule without a name?\n"); - /* skip this one but still delete other entries */ - continue; + if (delete_filter) { + ret = sysdb_sudo_purge_byfilter(domain, delete_filter); + } else { + ret = sysdb_sudo_purge_byrules(domain, rules, num_rules); + } + + if (ret != EOK) { + goto done; + } + + ret = sysdb_transaction_commit(domain->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(domain->sysdb); + if (sret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Could not cancel transaction\n"); } + } - ret = sysdb_sudo_purge_byname(domain, name); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Could not delete rule %s\n", name); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Unable to purge sudo cache [%d]: %s\n", + ret, sss_strerror(ret)); + } + + return ret; +} + +static errno_t +sysdb_sudo_add_sss_attrs(struct sysdb_attrs *rule, + const char *name, + int cache_timeout, + time_t now) +{ + time_t expire; + errno_t ret; + + ret = sysdb_attrs_add_string(rule, SYSDB_OBJECTCLASS, SYSDB_SUDO_CACHE_OC); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Unable to add %s attribute [%d]: %s\n", + SYSDB_OBJECTCLASS, ret, strerror(ret)); + return ret; + } + + ret = sysdb_attrs_add_string(rule, SYSDB_NAME, name); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Unable to add %s attribute [%d]: %s\n", + SYSDB_OBJECTCLASS, ret, strerror(ret)); + return ret; + } + + expire = cache_timeout > 0 ? now + cache_timeout : 0; + ret = sysdb_attrs_add_time_t(rule, SYSDB_CACHE_EXPIRE, expire); + if (ret) { + DEBUG(SSSDBG_OP_FAILURE, "Unable to add %s attribute [%d]: %s\n", + SYSDB_CACHE_EXPIRE, ret, strerror(ret)); + return ret; + } + + return EOK; +} + +static errno_t +sysdb_sudo_store_rule(struct sss_domain_info *domain, + struct sysdb_attrs *rule, + int cache_timeout, + time_t now) +{ + const char *name; + errno_t ret; + + name = sysdb_sudo_get_rule_name(rule); + if (name == NULL) { + return EINVAL; + } + + DEBUG(SSSDBG_TRACE_FUNC, "Adding sudo rule %s\n", name); + + ret = sysdb_sudo_add_sss_attrs(rule, name, cache_timeout, now); + if (ret != EOK) { + return ret; + } + + ret = sysdb_store_custom(domain, name, SUDORULE_SUBDIR, rule); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Unable to store rule %s [%d]: %s\n", + name, ret, strerror(ret)); + return ret; + } + + return EOK; +} + +errno_t +sysdb_sudo_store(struct sss_domain_info *domain, + struct sysdb_attrs **rules, + size_t num_rules) +{ + bool in_transaction = false; + errno_t sret; + errno_t ret; + time_t now; + size_t i; + + if (num_rules == 0 || rules == NULL) { + return EOK; + } + + ret = sysdb_transaction_start(domain->sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n"); + return ret; + } + in_transaction = true; + + now = time(NULL); + for (i = 0; i < num_rules; i++) { + ret = sysdb_sudo_store_rule(domain, rules[i], + domain->sudo_timeout, now); + if (ret == EINVAL) { + /* Multiple CNs are error on server side, we can just ignore this + * rule and save the others. Loud debug message is in logs. */ + continue; + } else if (ret != EOK) { goto done; } } @@ -720,6 +882,10 @@ done: } } - talloc_free(tmp_ctx); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Unable to store sudo rules [%d]: %s\n", + ret, sss_strerror(ret)); + } + return ret; } diff --git a/src/db/sysdb_sudo.h b/src/db/sysdb_sudo.h index fc896c385..6dd9ea7bb 100644 --- a/src/db/sysdb_sudo.h +++ b/src/db/sysdb_sudo.h @@ -78,20 +78,19 @@ sysdb_get_sudo_user_info(TALLOC_CTX *mem_ctx, const char *username, uid_t *_uid, char ***groupnames); -errno_t -sysdb_save_sudorule(struct sss_domain_info *domain, - const char *rule_name, - struct sysdb_attrs *attrs); - errno_t sysdb_sudo_set_last_full_refresh(struct sss_domain_info *domain, time_t value); errno_t sysdb_sudo_get_last_full_refresh(struct sss_domain_info *domain, time_t *value); -errno_t sysdb_sudo_purge_byname(struct sss_domain_info *domain, - const char *name); +errno_t sysdb_sudo_purge(struct sss_domain_info *domain, + const char *delete_filter, + struct sysdb_attrs **rules, + size_t num_rules); -errno_t sysdb_sudo_purge_byfilter(struct sss_domain_info *domain, - const char *filter); +errno_t +sysdb_sudo_store(struct sss_domain_info *domain, + struct sysdb_attrs **rules, + size_t num_rules); #endif /* _SYSDB_SUDO_H_ */ diff --git a/src/providers/ldap/sdap_async_sudo.c b/src/providers/ldap/sdap_async_sudo.c index d7780d384..2fcfa4aec 100644 --- a/src/providers/ldap/sdap_async_sudo.c +++ b/src/providers/ldap/sdap_async_sudo.c @@ -31,7 +31,6 @@ #include "providers/ldap/sdap.h" #include "providers/ldap/sdap_ops.h" #include "providers/ldap/sdap_sudo.h" -#include "providers/ldap/sdap_sudo_cache.h" #include "db/sysdb_sudo.h" struct sdap_sudo_load_sudoers_state { @@ -136,89 +135,6 @@ static int sdap_sudo_load_sudoers_recv(struct tevent_req *req, return EOK; } -static int sdap_sudo_purge_sudoers(struct sss_domain_info *dom, - const char *filter, - struct sdap_attr_map *map, - size_t rules_count, - struct sysdb_attrs **rules) -{ - const char *name; - size_t i; - errno_t ret; - - if (filter == NULL) { - /* removes downloaded rules from the cache */ - if (rules_count == 0 || rules == NULL) { - return EOK; - } - - for (i = 0; i < rules_count; i++) { - ret = sysdb_attrs_get_string(rules[i], - map[SDAP_AT_SUDO_NAME].sys_name, - &name); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, - "Failed to retrieve rule name: [%s]\n", strerror(ret)); - continue; - } - - ret = sysdb_sudo_purge_byname(dom, name); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, - "Failed to delete rule %s: [%s]\n", - name, strerror(ret)); - continue; - } - } - - ret = EOK; - } else { - /* purge cache by provided filter */ - ret = sysdb_sudo_purge_byfilter(dom, filter); - if (ret != EOK) { - goto done; - } - } - -done: - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "failed to purge sudo rules [%d]: %s\n", - ret, strerror(ret)); - } - - return ret; -} - -static int sdap_sudo_store_sudoers(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - struct sdap_options *opts, - size_t rules_count, - struct sysdb_attrs **rules, - int cache_timeout, - time_t now, - char **_usn) -{ - errno_t ret; - - /* Empty sudoers? Done. */ - if (rules_count == 0 || rules == NULL) { - *_usn = NULL; - return EOK; - } - - ret = sdap_save_native_sudorule_list(mem_ctx, domain, - opts->sudorule_map, rules, - rules_count, cache_timeout, now, - _usn); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "failed to save sudo rules [%d]: %s\n", - ret, strerror(ret)); - return ret; - } - - return EOK; -} - static void sdap_sudo_set_usn(struct sdap_server_opts *srv_opts, char *usn) { unsigned int usn_number; @@ -230,23 +146,14 @@ static void sdap_sudo_set_usn(struct sdap_server_opts *srv_opts, char *usn) } if (usn == NULL) { - /* If the USN value is unknown and we don't have max_sudo_value set - * (possibly first full refresh which did not find any rule) we will - * set zero so smart refresh can pick up. */ - if (srv_opts->max_sudo_value == NULL) { - srv_opts->max_sudo_value = talloc_strdup(srv_opts, "0"); - if (srv_opts->max_sudo_value == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n"); - } - return; - } - - DEBUG(SSSDBG_TRACE_FUNC, "Empty USN, ignoring\n"); + DEBUG(SSSDBG_TRACE_FUNC, "Bug: usn is NULL\n"); return; } - talloc_zfree(srv_opts->max_sudo_value); - srv_opts->max_sudo_value = talloc_steal(srv_opts, usn); + if (sysdb_compare_usn(usn, srv_opts->max_sudo_value) > 0) { + talloc_zfree(srv_opts->max_sudo_value); + srv_opts->max_sudo_value = talloc_steal(srv_opts, usn); + } usn_number = strtoul(usn, &endptr, 10); if ((endptr == NULL || (*endptr == '\0' && endptr != usn)) @@ -625,7 +532,6 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq) int ret; errno_t sret; bool in_transaction = false; - time_t now; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct sdap_sudo_refresh_state); @@ -654,17 +560,14 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq) in_transaction = true; /* purge cache */ - ret = sdap_sudo_purge_sudoers(state->domain, state->delete_filter, - state->opts->sudorule_map, rules_count, rules); + ret = sysdb_sudo_purge(state->domain, state->delete_filter, + rules, rules_count); if (ret != EOK) { goto done; } /* store rules */ - now = time(NULL); - ret = sdap_sudo_store_sudoers(state, state->domain, - state->opts, rules_count, rules, - state->domain->sudo_timeout, now, &usn); + ret = sysdb_sudo_store(state->domain, rules, rules_count); if (ret != EOK) { goto done; } @@ -680,7 +583,13 @@ static void sdap_sudo_refresh_done(struct tevent_req *subreq) DEBUG(SSSDBG_TRACE_FUNC, "Sudoers is successfuly stored in cache\n"); /* remember new usn */ - sdap_sudo_set_usn(state->srv_opts, usn); + ret = sysdb_get_highest_usn(state, rules, rules_count, &usn); + if (ret == EOK) { + sdap_sudo_set_usn(state->srv_opts, usn); + } else { + DEBUG(SSSDBG_MINOR_FAILURE, "Unable to get highest USN [%d]: %s\n", + ret, sss_strerror(ret)); + } ret = EOK; state->num_rules = rules_count; diff --git a/src/providers/ldap/sdap_sudo.c b/src/providers/ldap/sdap_sudo.c index 550784842..10067e9ba 100644 --- a/src/providers/ldap/sdap_sudo.c +++ b/src/providers/ldap/sdap_sudo.c @@ -27,7 +27,6 @@ #include "providers/ldap/sdap.h" #include "providers/ldap/sdap_async.h" #include "providers/ldap/sdap_sudo.h" -#include "providers/ldap/sdap_sudo_cache.h" #include "db/sysdb_sudo.h" static void sdap_sudo_handler(struct be_req *breq); diff --git a/src/providers/ldap/sdap_sudo_cache.c b/src/providers/ldap/sdap_sudo_cache.c deleted file mode 100644 index 56e84ce8f..000000000 --- a/src/providers/ldap/sdap_sudo_cache.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - Authors: - Jakub Hrozek <jhrozek@redhat.com> - - Copyright (C) 2011 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <talloc.h> - -#include "db/sysdb.h" -#include "db/sysdb_sudo.h" -#include "providers/ldap/sdap_sudo_cache.h" - -/* ========== Functions specific for the native sudo LDAP schema ========== */ -static errno_t sdap_sudo_get_usn(TALLOC_CTX *mem_ctx, - struct sysdb_attrs *attrs, - struct sdap_attr_map *map, - char **_usn) -{ - const char *usn; - errno_t ret; - - if (_usn == NULL) { - return EINVAL; - } - - ret = sysdb_attrs_get_string(attrs, map[SDAP_AT_SUDO_USN].sys_name, &usn); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, - "Failed to retrieve USN value: [%s]\n", strerror(ret)); - - return ret; - } - - *_usn = talloc_strdup(mem_ctx, usn); - if (*_usn == NULL) { - return ENOMEM; - } - - return EOK; -} - -static errno_t -sdap_save_native_sudorule(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - struct sdap_attr_map *map, - struct sysdb_attrs *attrs, - int cache_timeout, - time_t now, - char **_usn) -{ - errno_t ret; - const char *rule_name; - - ret = sysdb_attrs_get_string(attrs, map[SDAP_AT_SUDO_NAME].sys_name, - &rule_name); - if (ret == ERANGE) { - DEBUG(SSSDBG_OP_FAILURE, "Warning: found rule that contains none " - "or multiple CN values. It will be skipped.\n"); - return ret; - } else if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Could not get rule name [%d]: %s\n", - ret, strerror(ret)); - return ret; - } - - ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE, - (cache_timeout ? (now + cache_timeout) : 0)); - if (ret) { - DEBUG(SSSDBG_OP_FAILURE, "Could not set sysdb cache expire [%d]: %s\n", - ret, strerror(ret)); - return ret; - } - - ret = sdap_sudo_get_usn(mem_ctx, attrs, map, _usn); - if (ret != EOK) { - DEBUG(SSSDBG_MINOR_FAILURE, "Could not read USN from %s\n", rule_name); - *_usn = NULL; - /* but we will store the rule anyway */ - } - - ret = sysdb_save_sudorule(domain, rule_name, attrs); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, "Could not save sudorule %s\n", rule_name); - return ret; - } - - return ret; -} - -errno_t -sdap_save_native_sudorule_list(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - struct sdap_attr_map *map, - struct sysdb_attrs **replies, - size_t replies_count, - int cache_timeout, - time_t now, - char **_usn) -{ - TALLOC_CTX *tmp_ctx = NULL; - char *higher_usn = NULL; - char *usn_value = NULL; - errno_t ret, tret; - bool in_transaction = false; - size_t i; - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { - DEBUG(SSSDBG_FATAL_FAILURE, "talloc_new() failed\n"); - return ENOMEM; - } - - ret = sysdb_transaction_start(domain->sysdb); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Could not start transaction\n"); - goto fail; - } - in_transaction = true; - - for (i=0; i < replies_count; i++) { - usn_value = NULL; - ret = sdap_save_native_sudorule(tmp_ctx, domain, map, replies[i], - cache_timeout, now, &usn_value); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Failed to save sudo rule, " - "will continue with next...\n"); - continue; - } - - /* find highest usn */ - if (usn_value) { - if (higher_usn) { - if ((strlen(usn_value) > strlen(higher_usn)) || - (strcmp(usn_value, higher_usn) > 0)) { - talloc_zfree(higher_usn); - higher_usn = usn_value; - } else { - talloc_zfree(usn_value); - } - } else { - higher_usn = usn_value; - } - } - } - - ret = sysdb_transaction_commit(domain->sysdb); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n"); - goto fail; - } - in_transaction = false; - - if (higher_usn != NULL) { - *_usn = talloc_steal(mem_ctx, higher_usn); - } - - ret = EOK; -fail: - if (in_transaction) { - tret = sysdb_transaction_cancel(domain->sysdb); - if (tret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n"); - } - } - - talloc_free(tmp_ctx); - - return ret; -} diff --git a/src/providers/ldap/sdap_sudo_cache.h b/src/providers/ldap/sdap_sudo_cache.h deleted file mode 100644 index 5a756bf31..000000000 --- a/src/providers/ldap/sdap_sudo_cache.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - Authors: - Jakub Hrozek <jhrozek@redhat.com> - - Copyright (C) 2011 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _SDAP_SUDO_CACHE_H_ -#define _SDAP_SUDO_CACHE_H_ - -#include "src/providers/ldap/sdap.h" - -/* Cache functions specific for the native sudo LDAP schema */ -errno_t -sdap_save_native_sudorule_list(TALLOC_CTX *mem_ctx, - struct sss_domain_info *domain, - struct sdap_attr_map *map, - struct sysdb_attrs **replies, - size_t replies_count, - int cache_timeout, - time_t now, - char **_usn); - -#endif /* _SDAP_SUDO_CACHE_H_ */ |