diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 05:31:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 05:31:45 +0000 |
commit | 74aa0bc6779af38018a03fd2cf4419fe85917904 (patch) | |
tree | 9cb0681aac9a94a49c153d5823e7a55d1513d91f /src/db/sysdb_ssh.c | |
parent | Initial commit. (diff) | |
download | sssd-74aa0bc6779af38018a03fd2cf4419fe85917904.tar.xz sssd-74aa0bc6779af38018a03fd2cf4419fe85917904.zip |
Adding upstream version 2.9.4.upstream/2.9.4
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/db/sysdb_ssh.c')
-rw-r--r-- | src/db/sysdb_ssh.c | 401 |
1 files changed, 401 insertions, 0 deletions
diff --git a/src/db/sysdb_ssh.c b/src/db/sysdb_ssh.c new file mode 100644 index 0000000..4983dcc --- /dev/null +++ b/src/db/sysdb_ssh.c @@ -0,0 +1,401 @@ +/* + Authors: + Jan Cholasta <jcholast@redhat.com> + + Copyright (C) 2012 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_ssh.h" +#include "db/sysdb_private.h" + +static struct ldb_dn * +sysdb_ssh_host_dn(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *name) +{ + return sysdb_custom_dn(mem_ctx, domain, name, SSH_HOSTS_SUBDIR); +} + +static errno_t +sysdb_update_ssh_host(struct sss_domain_info *domain, + const char *name, + struct sysdb_attrs *attrs) +{ + errno_t ret; + + ret = sysdb_store_custom(domain, name, SSH_HOSTS_SUBDIR, + attrs); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Error storing host %s [%d]: %s\n", name, ret, strerror(ret)); + return ret; + } + + return EOK; +} + +errno_t +sysdb_store_ssh_host(struct sss_domain_info *domain, + const char *name, + const char *alias, + int cache_timeout, + time_t now, + struct sysdb_attrs *attrs) +{ + TALLOC_CTX *tmp_ctx; + errno_t ret, sret; + bool in_transaction = false; + const char *search_attrs[] = { SYSDB_NAME_ALIAS, NULL }; + bool new_alias; + struct ldb_message *host = NULL; + struct ldb_message_element *el; + unsigned int i; + + DEBUG(SSSDBG_TRACE_FUNC, "Storing host %s\n", name); + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + ret = sysdb_transaction_start(domain->sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n"); + goto done; + } + + in_transaction = true; + + ret = sysdb_get_ssh_host(tmp_ctx, domain, name, search_attrs, &host); + if (ret != EOK && ret != ENOENT) { + goto done; + } + + ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS, SYSDB_SSH_HOST_OC); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Could not set object class [%d]: %s\n", ret, strerror(ret)); + goto done; + } + + ret = sysdb_attrs_add_string(attrs, SYSDB_NAME, name); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Could not set name attribute [%d]: %s\n", ret, strerror(ret)); + goto done; + } + + if (alias) { + new_alias = true; + + /* copy aliases from the existing entry */ + if (host) { + el = ldb_msg_find_element(host, SYSDB_NAME_ALIAS); + + if (el) { + for (i = 0; i < el->num_values; i++) { + if (strcmp((char *)el->values[i].data, alias) == 0) { + new_alias = false; + } + + ret = sysdb_attrs_add_val(attrs, + SYSDB_NAME_ALIAS, &el->values[i]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Could not add name alias %s [%d]: %s\n", + el->values[i].data, ret, strerror(ret)); + goto done; + } + } + } + } + + /* add alias only if it is not already present */ + if (new_alias) { + ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, alias); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Could not add name alias %s [%d]: %s\n", + alias, ret, strerror(ret)); + goto done; + } + } + } + + /* make sure sshPublicKey is present when modifying an existing host */ + if (host) { + ret = sysdb_attrs_get_el(attrs, SYSDB_SSH_PUBKEY, &el); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Could not get sysdb sshPublicKey [%d]: %s\n", + ret, strerror(ret)); + goto done; + } + } + + ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Could not set sysdb lastUpdate [%d]: %s\n", + ret, strerror(ret)); + goto done; + } + + ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE, + cache_timeout ? (now + cache_timeout) : 0); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Could not set sysdb cache expire [%d]: %s\n", + ret, strerror(ret)); + goto done; + } + + ret = sysdb_update_ssh_host(domain, name, attrs); + 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; + + ret = EOK; + +done: + if (in_transaction) { + sret = sysdb_transaction_cancel(domain->sysdb); + if (sret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n"); + } + } + + talloc_free(tmp_ctx); + + return ret; +} + +errno_t +sysdb_set_ssh_host_attr(struct sss_domain_info *domain, + const char *name, + struct sysdb_attrs *attrs, + int mod_op) +{ + errno_t ret; + struct ldb_dn *dn; + TALLOC_CTX *tmp_ctx; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + dn = sysdb_ssh_host_dn(tmp_ctx, domain, name); + if (!dn) { + ret = ENOMEM; + goto done; + } + + ret = sysdb_set_entry_attr(domain->sysdb, dn, attrs, mod_op); + +done: + talloc_free(tmp_ctx); + return ret; +} + +errno_t +sysdb_update_ssh_known_host_expire(struct sss_domain_info *domain, + const char *name, + time_t now, + int known_hosts_timeout) +{ + TALLOC_CTX *tmp_ctx; + errno_t ret; + struct sysdb_attrs *attrs; + + DEBUG(SSSDBG_TRACE_FUNC, + "Updating known_hosts expire time of host %s\n", name); + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + attrs = sysdb_new_attrs(tmp_ctx); + if (!attrs) { + ret = ENOMEM; + goto done; + } + + ret = sysdb_attrs_add_time_t(attrs, SYSDB_SSH_KNOWN_HOSTS_EXPIRE, + now + known_hosts_timeout); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Could not set known_hosts expire time [%d]: %s\n", + ret, strerror(ret)); + goto done; + } + + ret = sysdb_update_ssh_host(domain, name, attrs); + if (ret != EOK) { + goto done; + } + + ret = EOK; + +done: + talloc_free(tmp_ctx); + + return ret; +} + +errno_t +sysdb_delete_ssh_host(struct sss_domain_info *domain, + const char *name) +{ + DEBUG(SSSDBG_TRACE_FUNC, "Deleting host %s\n", name); + return sysdb_delete_custom(domain, name, SSH_HOSTS_SUBDIR); +} + +errno_t +sysdb_search_ssh_hosts(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *filter, + const char **attrs, + size_t *num_hosts, + struct ldb_message ***hosts) +{ + errno_t ret; + TALLOC_CTX *tmp_ctx; + struct ldb_message **results; + size_t num_results; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + ret = sysdb_search_custom(tmp_ctx, domain, filter, + SSH_HOSTS_SUBDIR, attrs, + &num_results, &results); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Error looking up host [%d]: %s\n", + ret, strerror(ret)); + goto done; + } if (ret == ENOENT) { + DEBUG(SSSDBG_TRACE_FUNC, "No such host\n"); + *hosts = NULL; + *num_hosts = 0; + goto done; + } + + *hosts = talloc_steal(mem_ctx, results); + *num_hosts = num_results; + ret = EOK; + +done: + talloc_free(tmp_ctx); + + return ret; +} + +errno_t +sysdb_get_ssh_host(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *name, + const char **attrs, + struct ldb_message **host) +{ + TALLOC_CTX *tmp_ctx; + errno_t ret; + const char *filter; + struct ldb_message **hosts; + size_t num_hosts; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + filter = talloc_asprintf(tmp_ctx, "(%s=%s)", SYSDB_NAME, name); + if (!filter) { + ret = ENOMEM; + goto done; + } + + ret = sysdb_search_ssh_hosts(tmp_ctx, domain, filter, attrs, + &num_hosts, &hosts); + if (ret != EOK) { + goto done; + } + + if (num_hosts > 1) { + ret = EINVAL; + DEBUG(SSSDBG_CRIT_FAILURE, + "Found more than one host with name %s\n", name); + goto done; + } + + *host = talloc_steal(mem_ctx, hosts[0]); + ret = EOK; + +done: + talloc_free(tmp_ctx); + + return ret; +} + +errno_t +sysdb_get_ssh_known_hosts(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + time_t now, + const char **attrs, + struct ldb_message ***hosts, + size_t *num_hosts) +{ + TALLOC_CTX *tmp_ctx; + errno_t ret; + const char *filter; + + tmp_ctx = talloc_new(NULL); + if (!tmp_ctx) { + return ENOMEM; + } + + filter = talloc_asprintf(tmp_ctx, + "(&(|(!(%s=*))(%s=0)(%s>=%lld))(%s>=%lld))", + SYSDB_CACHE_EXPIRE, + SYSDB_CACHE_EXPIRE, + SYSDB_CACHE_EXPIRE, (long long)now + 1, + SYSDB_SSH_KNOWN_HOSTS_EXPIRE, (long long)now + 1); + if (!filter) { + ret = ENOMEM; + goto done; + } + + ret = sysdb_search_ssh_hosts(mem_ctx, domain, filter, attrs, + num_hosts, hosts); + +done: + talloc_free(tmp_ctx); + + return ret; +} |