sysdb_sudo.c revision 770896b194b7b66b09c2a30545b4d091fd86b1f4
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek Jakub Hrozek <jhrozek@redhat.com>
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek Copyright (C) 2011 Red Hat
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek This program is free software; you can redistribute it and/or modify
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek it under the terms of the GNU General Public License as published by
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek the Free Software Foundation; either version 3 of the License, or
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek (at your option) any later version.
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek This program is distributed in the hope that it will be useful,
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek but WITHOUT ANY WARRANTY; without even the implied warranty of
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek GNU General Public License for more details.
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek You should have received a copy of the GNU General Public License
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek along with this program. If not, see <http://www.gnu.org/licenses/>.
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek/* ==================== Utility functions ==================== */
80941dd89fd8bc7c4a1272c304f737ce0fd5fc54Sumit Bosestatic errno_t sysdb_sudo_convert_time(const char *str, time_t *unix_time)
5a2cce34cf8843613b0b9dfde054b3d471dd5f3aPavel Březina /* SUDO requires times to be in generalized time format:
5a2cce34cf8843613b0b9dfde054b3d471dd5f3aPavel Březina * YYYYMMDDHHMMSS[.|,fraction][(+|-HHMM)|Z]
5a2cce34cf8843613b0b9dfde054b3d471dd5f3aPavel Březina * We need to use more format strings to parse this with strptime().
5a2cce34cf8843613b0b9dfde054b3d471dd5f3aPavel Březina const char *formats[] = {"%Y%m%d%H%M%SZ", /* 201212121300Z */
5a2cce34cf8843613b0b9dfde054b3d471dd5f3aPavel Březina "%Y%m%d%H%M%S.0Z",
5a2cce34cf8843613b0b9dfde054b3d471dd5f3aPavel Březina "%Y%m%d%H%M%S.0%z",
5a2cce34cf8843613b0b9dfde054b3d471dd5f3aPavel Březina "%Y%m%d%H%M%S,0Z",
5a2cce34cf8843613b0b9dfde054b3d471dd5f3aPavel Březina "%Y%m%d%H%M%S,0%z",
5a2cce34cf8843613b0b9dfde054b3d471dd5f3aPavel Březina for (format = formats; *format != NULL; format++) {
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březinastatic errno_t sysdb_sudo_check_time(struct sysdb_attrs *rule,
db419c61035cb262010cc8d5a4047191c2b60f05Pavel Březina ret = sysdb_attrs_get_string(rule, SYSDB_SUDO_CACHE_AT_CN, &name);
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina * From man sudoers.ldap:
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina * If multiple sudoNotBefore entries are present, the *earliest* is used.
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina * If multiple sudoNotAfter entries are present, the *last one* is used.
4be402505ba20b43361753f0e6e1589c9b029e81Jakub Hrozek * From sudo sources, ldap.c:
4be402505ba20b43361753f0e6e1589c9b029e81Jakub Hrozek * If either the sudoNotAfter or sudoNotBefore attributes are missing,
4be402505ba20b43361753f0e6e1589c9b029e81Jakub Hrozek * no time restriction shall be imposed.
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina /* check for sudoNotBefore */
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina ret = sysdb_attrs_get_string_array(rule, SYSDB_SUDO_CACHE_AT_NOTBEFORE,
db419c61035cb262010cc8d5a4047191c2b60f05Pavel Březina ("notBefore attribute is missing, the rule [%s] is valid\n",
4be402505ba20b43361753f0e6e1589c9b029e81Jakub Hrozek for (i=0; values[i] ; i++) {
5a2cce34cf8843613b0b9dfde054b3d471dd5f3aPavel Březina ret = sysdb_sudo_convert_time(values[i], &converted);
db419c61035cb262010cc8d5a4047191c2b60f05Pavel Březina DEBUG(SSSDBG_MINOR_FAILURE, ("Invalid time format in rule [%s]!\n",
4be402505ba20b43361753f0e6e1589c9b029e81Jakub Hrozek /* Grab the earliest */
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina /* check for sudoNotAfter */
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina ret = sysdb_attrs_get_string_array(rule, SYSDB_SUDO_CACHE_AT_NOTAFTER,
db419c61035cb262010cc8d5a4047191c2b60f05Pavel Březina ("notAfter attribute is missing, the rule [%s] is valid\n",
4be402505ba20b43361753f0e6e1589c9b029e81Jakub Hrozek for (i=0; values[i] ; i++) {
5a2cce34cf8843613b0b9dfde054b3d471dd5f3aPavel Březina ret = sysdb_sudo_convert_time(values[i], &converted);
db419c61035cb262010cc8d5a4047191c2b60f05Pavel Březina DEBUG(SSSDBG_MINOR_FAILURE, ("Invalid time format in rule [%s]!\n",
4be402505ba20b43361753f0e6e1589c9b029e81Jakub Hrozek /* Grab the latest */
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březinaerrno_t sysdb_sudo_filter_rules_by_time(TALLOC_CTX *mem_ctx,
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina bool allowed = false;
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina for (i = 0; i < in_num_rules; i++) {
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina ret = sysdb_sudo_check_time(in_rules[i], now, &allowed);
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina rules = talloc_realloc(tmp_ctx, rules, struct sysdb_attrs *,
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozeksysdb_get_sudo_filter(TALLOC_CTX *mem_ctx, const char *username,
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek uid_t uid, char **groupnames, unsigned int flags,
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina /* build specific filter */
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina specific_filter = talloc_zero(tmp_ctx, char); /* assign to tmp_ctx */
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina specific_filter = talloc_asprintf_append(specific_filter, "(%s=ALL)",
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina specific_filter = talloc_asprintf_append(specific_filter, "(%s=defaults)",
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina if ((flags & SYSDB_SUDO_FILTER_USERNAME) && (username != NULL)) {
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina specific_filter = talloc_asprintf_append(specific_filter, "(%s=%s)",
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina if ((flags & SYSDB_SUDO_FILTER_UID) && (uid != 0)) {
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina specific_filter = talloc_asprintf_append(specific_filter, "(%s=#%llu)",
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina (unsigned long long) uid);
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina if ((flags & SYSDB_SUDO_FILTER_GROUPS) && (groupnames != NULL)) {
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina specific_filter = talloc_asprintf_append(specific_filter, "(%s=%%%s)",
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina specific_filter = talloc_asprintf_append(specific_filter, "(%s=+*)",
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina /* build global filter */
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina filter = talloc_asprintf(tmp_ctx, "(&(%s=%s)",
f6171b2bc954a367f316853ab71090eb213bdee3Pavel Březina filter = talloc_asprintf_append(filter, "(|%s)", specific_filter);
f7af8c5b369938725e47585c641ae5b017d442a1Pavel Březina filter = talloc_asprintf_append(filter, "(&(%s<=%lld))",
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozeksysdb_get_sudo_user_info(TALLOC_CTX *mem_ctx, const char *username,
2ce00e0d3896bb42db169d1e79553a81ca837a22Simo Sorce ret = sysdb_search_user_by_name(tmp_ctx, sysdb, sysdb->domain,
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek DEBUG(SSSDBG_CRIT_FAILURE, ("Error looking up user %s\n", username));
cda8ff6cfdef22356dc3c06ec5204344912f0f0bPavel Březina uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
cda8ff6cfdef22356dc3c06ec5204344912f0f0bPavel Březina DEBUG(SSSDBG_CRIT_FAILURE, ("A user with no UID?\n"));
e7b5b99e5a5d276f32039c4fb8b21ba51bdb1537Pavel Březina /* resolve secondary groups */
cda8ff6cfdef22356dc3c06ec5204344912f0f0bPavel Březina groups = ldb_msg_find_element(msg, SYSDB_MEMBEROF);
cda8ff6cfdef22356dc3c06ec5204344912f0f0bPavel Březina /* No groups for this user in sysdb currently */
e7b5b99e5a5d276f32039c4fb8b21ba51bdb1537Pavel Březina sysdb_groupnames = talloc_array(tmp_ctx, char *, num_groups + 1);
cda8ff6cfdef22356dc3c06ec5204344912f0f0bPavel Březina /* Get a list of the groups by groupname only */
e7b5b99e5a5d276f32039c4fb8b21ba51bdb1537Pavel Březina /* resolve primary group */
e7b5b99e5a5d276f32039c4fb8b21ba51bdb1537Pavel Březina gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
5d72a91a37273c8c874640906fd2f7a70e606812Simo Sorce ret = sysdb_search_group_by_gid(tmp_ctx, sysdb, sysdb->domain, gid,
e7b5b99e5a5d276f32039c4fb8b21ba51bdb1537Pavel Březina primary_group = ldb_msg_find_attr_as_string(group_msg, SYSDB_NAME,
e7b5b99e5a5d276f32039c4fb8b21ba51bdb1537Pavel Březina sysdb_groupnames = talloc_realloc(tmp_ctx, sysdb_groupnames,
e7b5b99e5a5d276f32039c4fb8b21ba51bdb1537Pavel Březina sysdb_groupnames[num_groups - 1] = talloc_strdup(sysdb_groupnames,
e7b5b99e5a5d276f32039c4fb8b21ba51bdb1537Pavel Březina NULL_CHECK(sysdb_groupnames[num_groups - 1], ret, done);
e7b5b99e5a5d276f32039c4fb8b21ba51bdb1537Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, ("Error looking up group [%d]: %s\n",
cda8ff6cfdef22356dc3c06ec5204344912f0f0bPavel Březina *groupnames = talloc_steal(mem_ctx, sysdb_groupnames);
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozeksysdb_save_sudorule(struct sysdb_ctx *sysdb_ctx,
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek DEBUG(SSSDBG_TRACE_FUNC, ("Adding sudo rule %s\n", rule_name));
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS,
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, ("Could not set rule object class [%d]: %s\n",
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek ret = sysdb_attrs_add_string(attrs, SYSDB_NAME, rule_name);
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, ("Could not set name attribute [%d]: %s\n",
dd7192379e5fc5bb852863e60ad4b6a20c5da183Simo Sorce ret = sysdb_store_custom(sysdb_ctx, sysdb_ctx->domain, rule_name, SUDORULE_SUBDIR, attrs);
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, ("sysdb_store_custom failed [%d]: %s\n",
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březinastatic errno_t sysdb_sudo_set_refresh_time(struct sysdb_ctx *sysdb,
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březina dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_CUSTOM_SUBTREE,
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březina lret = ldb_search(sysdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březina lret = ldb_msg_add_string(msg, "cn", SUDORULE_SUBDIR);
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březina ("Got more than one reply for base search!\n"));
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březina lret = ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_REPLACE, NULL);
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březina lret = ldb_msg_add_fmt(msg, attr_name, "%lld", (long long)value);
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březinastatic errno_t sysdb_sudo_get_refresh_time(struct sysdb_ctx *sysdb,
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březina dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, SYSDB_TMPL_CUSTOM_SUBTREE,
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březina lret = ldb_search(sysdb->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březina /* This entry has not been populated in LDB
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březina * This is a common case, as unlike LDAP,
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březina * LDB does not need to have all of its parent
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březina * objects actually exist.
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březina ("Got more than one reply for base search!\n"));
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březina *value = ldb_msg_find_attr_as_int(res->msgs[0], attr_name, 0);
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březinaerrno_t sysdb_sudo_set_last_full_refresh(struct sysdb_ctx *sysdb, time_t value)
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březina return sysdb_sudo_set_refresh_time(sysdb, SYSDB_SUDO_AT_LAST_FULL_REFRESH,
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březinaerrno_t sysdb_sudo_get_last_full_refresh(struct sysdb_ctx *sysdb, time_t *value)
44749ce0c1fee9babee80060fa0db99eebb2ab51Pavel Březina return sysdb_sudo_get_refresh_time(sysdb, SYSDB_SUDO_AT_LAST_FULL_REFRESH,
f5d4b05027acce06e3509ecb68869d1c7ef37180Pavel Březina/* ==================== Purge functions ==================== */
9675bccabff4e79d224f64611ad9ff3e073b488eSimo Sorcestatic errno_t sysdb_sudo_purge_all(struct sysdb_ctx *sysdb,
9675bccabff4e79d224f64611ad9ff3e073b488eSimo Sorce base_dn = sysdb_custom_subtree_dn(sysdb, tmp_ctx, domain, SUDORULE_SUBDIR);
f5d4b05027acce06e3509ecb68869d1c7ef37180Pavel Březina ret = sysdb_delete_recursive(sysdb, base_dn, true);
f5d4b05027acce06e3509ecb68869d1c7ef37180Pavel Březina DEBUG(SSSDBG_OP_FAILURE, ("sysdb_delete_recursive failed.\n"));
f5d4b05027acce06e3509ecb68869d1c7ef37180Pavel Březinaerrno_t sysdb_sudo_purge_byname(struct sysdb_ctx *sysdb,
f5d4b05027acce06e3509ecb68869d1c7ef37180Pavel Březina DEBUG(SSSDBG_TRACE_INTERNAL, ("Deleting sudo rule %s\n", name));
f5d4b05027acce06e3509ecb68869d1c7ef37180Pavel Březina return sysdb_delete_custom(sysdb, name, SUDORULE_SUBDIR);
f5d4b05027acce06e3509ecb68869d1c7ef37180Pavel Březinaerrno_t sysdb_sudo_purge_byfilter(struct sysdb_ctx *sysdb,
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek const char *name;
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek /* just purge all if there's no filter */
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek /* match entries based on the filter and remove them one by one */
770896b194b7b66b09c2a30545b4d091fd86b1f4Simo Sorce ret = sysdb_search_custom(tmp_ctx, sysdb, domain, filter,
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek DEBUG(SSSDBG_TRACE_FUNC, ("No rules matched\n"));
f5d4b05027acce06e3509ecb68869d1c7ef37180Pavel Březina DEBUG(SSSDBG_CRIT_FAILURE, ("Error looking up SUDO rules"));
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n"));
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek for (i = 0; i < count; i++) {
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek name = ldb_msg_find_attr_as_string(msgs[i], SYSDB_NAME, NULL);
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, ("A rule without a name?\n"));
f643754db81eeade60485bbe3d80324d889cc4f3Pavel Březina /* skip this one but still delete other entries */
3f98cdc011bb4e8cd22c088f288b0bcdb6452492Jakub Hrozek DEBUG(SSSDBG_OP_FAILURE, ("Could not delete rule %s\n", name));
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
f5d4b05027acce06e3509ecb68869d1c7ef37180Pavel Březina DEBUG(SSSDBG_OP_FAILURE, ("Could not cancel transaction\n"));