From b193250ca7b71e4f07f3016e0addbc4ba521c6a5 Mon Sep 17 00:00:00 2001 From: Jan Cholasta Date: Fri, 24 Feb 2012 12:48:08 -0500 Subject: SSH: Save SSH host name aliases --- src/db/sysdb_ssh.c | 85 ++++++++++++++++++++++++++++++++++---- src/db/sysdb_ssh.h | 9 ++-- src/providers/data_provider_be.c | 4 +- src/providers/ipa/ipa_hostid.c | 34 ++++----------- src/responder/ssh/sshsrv_cmd.c | 26 +++++++++++- src/responder/ssh/sshsrv_private.h | 1 + 6 files changed, 119 insertions(+), 40 deletions(-) diff --git a/src/db/sysdb_ssh.c b/src/db/sysdb_ssh.c index c2ea35b03..d83ad9669 100644 --- a/src/db/sysdb_ssh.c +++ b/src/db/sysdb_ssh.c @@ -24,12 +24,19 @@ #include "db/sysdb_private.h" errno_t -sysdb_save_ssh_host(struct sysdb_ctx *sysdb_ctx, - const char *name, - struct sysdb_attrs *attrs) +sysdb_store_ssh_host(struct sysdb_ctx *sysdb, + const char *name, + const char *alias, + struct sysdb_attrs *attrs) { - errno_t ret; TALLOC_CTX *tmp_ctx; + errno_t ret; + struct ldb_message **hosts; + size_t num_hosts; + struct ldb_message_element *el; + unsigned int i; + const char *search_attrs[] = { SYSDB_NAME_ALIAS, NULL }; + bool in_transaction = false; DEBUG(SSSDBG_TRACE_FUNC, ("Adding host %s\n", name)); @@ -46,25 +53,89 @@ sysdb_save_ssh_host(struct sysdb_ctx *sysdb_ctx, } } - ret = sysdb_store_custom(sysdb_ctx, name, SSH_HOSTS_SUBDIR, attrs); + ret = sysdb_transaction_start(sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + ("Failed to start update transaction\n")); + goto done; + } + + in_transaction = true; + + ret = sysdb_search_ssh_hosts(tmp_ctx, sysdb, name, search_attrs, + &hosts, &num_hosts); + if (ret != EOK && ret != ENOENT) { + goto done; + } + + if (num_hosts > 1) { + ret = EINVAL; + goto done; + } + + ret = sysdb_delete_ssh_host(sysdb, name); + if (ret != EOK && ret != ENOENT) { + goto done; + } + + if (num_hosts == 1) { + el = ldb_msg_find_element(hosts[0], SYSDB_NAME_ALIAS); + + if (el) { + for (i = 0; i < el->num_values; i++) { + if (alias && strcmp((char *)el->values[i].data, alias) == 0) { + alias = NULL; + } + + ret = sysdb_attrs_add_val(attrs, + SYSDB_NAME_ALIAS, &el->values[i]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Could not add name alias\n")); + goto done; + } + } + } + } + + if (alias) { + ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, alias); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, ("Could not add name alias\n")); + goto done; + } + } + + ret = sysdb_store_custom(sysdb, name, SSH_HOSTS_SUBDIR, attrs); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, ("sysdb_store_custom failed [%d]: %s\n", ret, strerror(ret))); goto done; } + ret = sysdb_transaction_commit(sysdb); + if (ret != EOK) { + goto done; + } + + in_transaction = false; ret = EOK; + done: + if (in_transaction) { + sysdb_transaction_cancel(sysdb); + } + talloc_free(tmp_ctx); + return ret; } errno_t -sysdb_delete_ssh_host(struct sysdb_ctx *sysdb_ctx, +sysdb_delete_ssh_host(struct sysdb_ctx *sysdb, const char *name) { DEBUG(SSSDBG_TRACE_FUNC, ("Deleting host %s\n", name)); - return sysdb_delete_custom(sysdb_ctx, name, SSH_HOSTS_SUBDIR); + return sysdb_delete_custom(sysdb, name, SSH_HOSTS_SUBDIR); } errno_t diff --git a/src/db/sysdb_ssh.h b/src/db/sysdb_ssh.h index f9d8d6eca..3136dcc07 100644 --- a/src/db/sysdb_ssh.h +++ b/src/db/sysdb_ssh.h @@ -26,12 +26,13 @@ #define SSH_HOSTS_SUBDIR "ssh_hosts" errno_t -sysdb_save_ssh_host(struct sysdb_ctx *sysdb_ctx, - const char *name, - struct sysdb_attrs *attrs); +sysdb_store_ssh_host(struct sysdb_ctx *sysdb, + const char *name, + const char *alias, + struct sysdb_attrs *attrs); errno_t -sysdb_delete_ssh_host(struct sysdb_ctx *sysdb_ctx, +sysdb_delete_ssh_host(struct sysdb_ctx *sysdb, const char *name); errno_t diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c index 2cea1933c..7e27ceacd 100644 --- a/src/providers/data_provider_be.c +++ b/src/providers/data_provider_be.c @@ -1182,7 +1182,9 @@ static int be_host_handler(DBusMessage *message, struct sbus_connection *conn) if (filter) { if (strncmp(filter, "name=", 5) == 0) { req->filter_type = BE_FILTER_NAME; - req->filter_value = &filter[5]; + ret = split_service_name_filter(req, &filter[5], + &req->filter_value, + &req->extra_value); } else { err_maj = DP_ERR_FATAL; err_min = EINVAL; diff --git a/src/providers/ipa/ipa_hostid.c b/src/providers/ipa/ipa_hostid.c index 873cc5296..8ab24fe5a 100644 --- a/src/providers/ipa/ipa_hostid.c +++ b/src/providers/ipa/ipa_hostid.c @@ -33,6 +33,7 @@ struct hosts_get_state { struct sysdb_ctx *sysdb; struct sss_domain_info *domain; const char *name; + const char *alias; const char **attrs; size_t count; @@ -45,6 +46,7 @@ hosts_get_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct ipa_hostid_ctx *hostid_ctx, const char *name, + const char *alias, int attrs_type); static errno_t hosts_get_recv(struct tevent_req *req, @@ -83,7 +85,7 @@ ipa_host_info_handler(struct be_req *breq) } req = hosts_get_send(breq, breq->be_ctx->ev, hostid_ctx, - ar->filter_value, + ar->filter_value, ar->extra_value, ar->attr_type); if (!req) { ret = ENOMEM; @@ -149,6 +151,7 @@ hosts_get_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct ipa_hostid_ctx *hostid_ctx, const char *name, + const char *alias, int attrs_type) { struct tevent_req *req; @@ -175,6 +178,7 @@ hosts_get_send(TALLOC_CTX *memctx, state->sysdb = ctx->be->sysdb; state->domain = ctx->be->domain; state->name = name; + state->alias = alias; /* TODO: handle attrs_type */ ret = build_attrs_from_map(state, ctx->opts->host_map, @@ -253,7 +257,6 @@ hosts_get_done(struct tevent_req *subreq) struct hosts_get_state); int dp_error = DP_ERR_FATAL; errno_t ret; - bool in_transaction = false; ret = ipa_host_info_recv(subreq, state, &state->count, &state->hosts, @@ -274,20 +277,6 @@ hosts_get_done(struct tevent_req *subreq) goto done; } - ret = sysdb_transaction_start(state->sysdb); - if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - ("Failed to start update transaction\n")); - goto done; - } - - in_transaction = true; - - ret = sysdb_delete_ssh_host(state->sysdb, state->name); - if (ret != EOK && ret != ENOENT) { - goto done; - } - if (state->count == 0) { DEBUG(SSSDBG_CRIT_FAILURE, ("No host with name [%s] found.\n", state->name)); @@ -302,18 +291,12 @@ hosts_get_done(struct tevent_req *subreq) goto done; } - ret = sysdb_save_ssh_host(state->sysdb, - state->name, state->hosts[0]); + ret = sysdb_store_ssh_host(state->sysdb, state->name, state->alias, + state->hosts[0]); if (ret != EOK) { goto done; } - ret = sysdb_transaction_commit(state->sysdb); - if (ret != EOK) { - goto done; - } - - in_transaction = false; dp_error = DP_ERR_OK; done: @@ -321,9 +304,6 @@ done: if (ret == EOK) { tevent_req_done(req); } else { - if (in_transaction) { - sysdb_transaction_cancel(state->sysdb); - } tevent_req_error(req, ret); } } diff --git a/src/responder/ssh/sshsrv_cmd.c b/src/responder/ssh/sshsrv_cmd.c index 0a182f310..da6a4540b 100644 --- a/src/responder/ssh/sshsrv_cmd.c +++ b/src/responder/ssh/sshsrv_cmd.c @@ -22,6 +22,7 @@ #include #include +#include #include "util/util.h" #include "util/crypto/sss_crypto.h" @@ -90,6 +91,8 @@ sss_ssh_cmd_get_host_pubkeys(struct cli_ctx *cctx) { struct ssh_cmd_ctx *cmd_ctx; errno_t ret; + struct addrinfo ai_hint; + struct addrinfo *ai = NULL; cmd_ctx = talloc_zero(cctx, struct ssh_cmd_ctx); if (!cmd_ctx) { @@ -107,6 +110,27 @@ sss_ssh_cmd_get_host_pubkeys(struct cli_ctx *cctx) ("Requesting SSH host public keys for [%s] from [%s]\n", cmd_ctx->name, cmd_ctx->domname ? cmd_ctx->domname : "")); + /* canonicalize host name */ + memset(&ai_hint, 0, sizeof(struct addrinfo)); + ai_hint.ai_flags = AI_CANONNAME; + + ret = getaddrinfo(cmd_ctx->name, NULL, &ai_hint, &ai); + if (!ret) { + if (strcmp(cmd_ctx->name, ai[0].ai_canonname) != 0) { + cmd_ctx->alias = cmd_ctx->name; + cmd_ctx->name = talloc_strdup(cmd_ctx, ai[0].ai_canonname); + if (!cmd_ctx->name) { + ret = ENOMEM; + goto done; + } + } + } else { + DEBUG(SSSDBG_OP_FAILURE, + ("getaddrinfo() failed (%d): %s\n", ret, gai_strerror(ret))); + } + + freeaddrinfo(ai); + if (cmd_ctx->domname) { cmd_ctx->domain = responder_get_domain(cctx->rctx->domains, cmd_ctx->domname); @@ -312,7 +336,7 @@ ssh_host_pubkeys_search(struct ssh_cmd_ctx *cmd_ctx) if (NEED_CHECK_PROVIDER(cmd_ctx->domain->provider)) { req = sss_dp_get_account_send(cmd_ctx, cmd_ctx->cctx->rctx, cmd_ctx->domain, false, SSS_DP_HOST, - cmd_ctx->name, 0, NULL); + cmd_ctx->name, 0, cmd_ctx->alias); if (!req) { DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory sending data provider request\n")); diff --git a/src/responder/ssh/sshsrv_private.h b/src/responder/ssh/sshsrv_private.h index 26ed6b92e..ffe88eb35 100644 --- a/src/responder/ssh/sshsrv_private.h +++ b/src/responder/ssh/sshsrv_private.h @@ -34,6 +34,7 @@ struct ssh_cmd_ctx { struct cli_ctx *cctx; enum sss_dp_acct_type type; char *name; + char *alias; char *domname; struct sss_domain_info *domain; -- cgit