a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina/*
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina Authors:
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina Jan Cholasta <jcholast@redhat.com>
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina Copyright (C) 2012 Red Hat
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina This program is free software; you can redistribute it and/or modify
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina it under the terms of the GNU General Public License as published by
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina the Free Software Foundation; either version 3 of the License, or
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina (at your option) any later version.
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina This program is distributed in the hope that it will be useful,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina but WITHOUT ANY WARRANTY; without even the implied warranty of
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina GNU General Public License for more details.
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina You should have received a copy of the GNU General Public License
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina along with this program. If not, see <http://www.gnu.org/licenses/>.
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina*/
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina#include "config.h"
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina#include <talloc.h>
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina#include "util/util.h"
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina#include "util/crypto/sss_crypto.h"
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina#include "util/sss_ssh.h"
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina#include "db/sysdb.h"
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina#include "db/sysdb_ssh.h"
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina#include "responder/ssh/ssh_private.h"
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březinastatic char *
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březinassh_host_pubkeys_format_known_host_plain(TALLOC_CTX *mem_ctx,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina struct sss_ssh_ent *ent)
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina{
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina TALLOC_CTX *tmp_ctx;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina errno_t ret;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina char *name, *pubkey;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina char *result = NULL;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina size_t i;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina tmp_ctx = talloc_new(NULL);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (!tmp_ctx) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina return NULL;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina name = talloc_strdup(tmp_ctx, ent->name);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (!name) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina for (i = 0; i < ent->num_aliases; i++) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina name = talloc_asprintf_append(name, ",%s", ent->aliases[i]);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (!name) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina result = talloc_strdup(tmp_ctx, "");
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (!result) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina for (i = 0; i < ent->num_pubkeys; i++) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina ret = sss_ssh_format_pubkey(tmp_ctx, &ent->pubkeys[i], &pubkey);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (ret != EOK) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina result = NULL;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina result = talloc_asprintf_append(result, "%s %s\n", name, pubkey);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (!result) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina talloc_free(pubkey);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina talloc_steal(mem_ctx, result);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březinadone:
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina talloc_free(tmp_ctx);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina return result;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina}
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březinastatic char *
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březinassh_host_pubkeys_format_known_host_hashed(TALLOC_CTX *mem_ctx,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina struct sss_ssh_ent *ent)
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina{
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina TALLOC_CTX *tmp_ctx;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina errno_t ret;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina char *name, *pubkey, *saltstr, *hashstr, *result;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina unsigned char salt[SSS_SHA1_LENGTH], hash[SSS_SHA1_LENGTH];
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina size_t i, j, k;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina tmp_ctx = talloc_new(NULL);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (!tmp_ctx) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina return NULL;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina result = talloc_strdup(tmp_ctx, "");
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (!result) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina for (i = 0; i < ent->num_pubkeys; i++) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina ret = sss_ssh_format_pubkey(tmp_ctx, &ent->pubkeys[i], &pubkey);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (ret != EOK) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina result = NULL;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina for (j = 0; j <= ent->num_aliases; j++) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina name = (j == 0 ? ent->name : ent->aliases[j-1]);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina for (k = 0; k < SSS_SHA1_LENGTH; k++) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina salt[k] = rand();
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina ret = sss_hmac_sha1(salt, SSS_SHA1_LENGTH,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina (unsigned char *)name, strlen(name),
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina hash);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (ret != EOK) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina DEBUG(SSSDBG_OP_FAILURE,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina "sss_hmac_sha1() failed (%d): %s\n",
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina ret, strerror(ret));
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina result = NULL;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina saltstr = sss_base64_encode(tmp_ctx, salt, SSS_SHA1_LENGTH);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (!saltstr) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina result = NULL;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina hashstr = sss_base64_encode(tmp_ctx, hash, SSS_SHA1_LENGTH);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (!hashstr) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina result = NULL;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina result = talloc_asprintf_append(result, "|1|%s|%s %s\n",
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina saltstr, hashstr, pubkey);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (!result) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina talloc_free(saltstr);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina talloc_free(hashstr);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina talloc_free(pubkey);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina talloc_steal(mem_ctx, result);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březinadone:
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina talloc_free(tmp_ctx);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina return result;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina}
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březinastatic errno_t
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březinassh_write_known_hosts(struct sss_domain_info *domains,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina bool hash_known_hosts,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina time_t now,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina int fd)
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina{
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina TALLOC_CTX *tmp_ctx;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina struct sss_domain_info *dom;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina struct ldb_message **hosts;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina struct sysdb_ctx *sysdb;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina struct sss_ssh_ent *ent;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina char *entstr;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina size_t num_hosts;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina size_t i;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina ssize_t wret;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina errno_t ret;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina static const char *attrs[] = {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina SYSDB_NAME,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina SYSDB_NAME_ALIAS,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina SYSDB_SSH_PUBKEY,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina NULL
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina };
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina tmp_ctx = talloc_new(NULL);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (tmp_ctx == NULL) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory!\n");
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina return ENOMEM;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina for (dom = domains; dom != NULL; dom = get_next_domain(dom, false)) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina sysdb = dom->sysdb;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (sysdb == NULL) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina DEBUG(SSSDBG_FATAL_FAILURE,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina "Fatal: Sysdb CTX not found for this domain!\n");
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina ret = EFAULT;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina ret = sysdb_get_ssh_known_hosts(tmp_ctx, dom, now, attrs,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina &hosts, &num_hosts);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (ret == ENOENT) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina continue;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina } else if (ret != EOK) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina DEBUG(SSSDBG_OP_FAILURE, "Host search failed for domain "
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina "%s [%d]: %s\n", dom->name, ret, sss_strerror(ret));
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina continue;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina for (i = 0; i < num_hosts; i++) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina ret = sss_ssh_make_ent(tmp_ctx, hosts[i], &ent);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (ret != EOK) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina DEBUG(SSSDBG_OP_FAILURE,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina "Failed to get SSH host public keys\n");
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina continue;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (hash_known_hosts) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina entstr = ssh_host_pubkeys_format_known_host_hashed(ent, ent);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina } else {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina entstr = ssh_host_pubkeys_format_known_host_plain(ent, ent);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (entstr == NULL) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina DEBUG(SSSDBG_OP_FAILURE, "Failed to format known_hosts data "
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina "for [%s]\n", ent->name);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina continue;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina wret = sss_atomic_write_s(fd, entstr, strlen(entstr));
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (wret == -1) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina ret = errno;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina talloc_free(ent);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina talloc_free(hosts);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina ret = EOK;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březinadone:
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina talloc_free(tmp_ctx);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina return ret;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina}
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březinaerrno_t
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březinassh_update_known_hosts_file(struct sss_domain_info *domains,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina struct sss_domain_info *domain,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina const char *name,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina bool hash_known_hosts,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina int known_hosts_timeout)
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina{
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina TALLOC_CTX *tmp_ctx;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina char *filename;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina errno_t ret;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina time_t now;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina int fd = -1;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina tmp_ctx = talloc_new(NULL);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (tmp_ctx == NULL) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory!\n");
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina return ENOMEM;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina now = time(NULL);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina /* Update host's expiration time. */
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (domain != NULL) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina ret = sysdb_update_ssh_known_host_expire(domain, name, now,
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina known_hosts_timeout);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (ret != EOK && ret != ENOENT) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina /* Create temporary known hosts file. */
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina filename = talloc_strdup(tmp_ctx, SSS_SSH_KNOWN_HOSTS_TEMP_TMPL);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (filename == NULL) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina ret = ENOMEM;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina fd = sss_unique_file_ex(tmp_ctx, filename, 0133, &ret);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (fd == -1) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina filename = NULL;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina /* Write contents. */
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina ret = ssh_write_known_hosts(domains, hash_known_hosts, now, fd);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (ret != EOK) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina DEBUG(SSSDBG_CRIT_FAILURE, "Unable to write known hosts file "
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina "[%d]: %s\n", ret, sss_strerror(ret));
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina /* Rename to SSH known hosts file. */
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina ret = fchmod(fd, 0644);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (ret == -1) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina ret = errno;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina ret = rename(filename, SSS_SSH_KNOWN_HOSTS_PATH);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (ret == -1) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina ret = errno;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina goto done;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina ret = EOK;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březinadone:
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina talloc_free(tmp_ctx);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina if (fd != -1) {
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina close(fd);
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina }
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina return ret;
a8191ce7ad5364801ad9458c3194075a7ca77b8aPavel Březina}