From c49e9718867874a6728bc77464f4ee8bb058832e Mon Sep 17 00:00:00 2001 From: Jan Cholasta Date: Feb 27 2012 17:16:51 +0000 Subject: SSH: Replace blocking getaddrinfo call in the responder with asynchronous resolver code --- diff --git a/Makefile.am b/Makefile.am index a1fafcd..8158165 100644 --- a/Makefile.am +++ b/Makefile.am @@ -533,9 +533,11 @@ if BUILD_SSH sssd_ssh_SOURCES = \ src/responder/ssh/sshsrv.c \ src/responder/ssh/sshsrv_cmd.c \ - $(SSSD_RESPONDER_OBJ) + $(SSSD_RESPONDER_OBJ) \ + $(SSSD_RESOLV_OBJ) sssd_ssh_LDADD = \ $(SSSD_LIBS) \ + $(CARES_LIBS) \ libsss_util.la endif diff --git a/src/responder/ssh/sshsrv.c b/src/responder/ssh/sshsrv.c index e5bb5b0..5231dc9 100644 --- a/src/responder/ssh/sshsrv.c +++ b/src/responder/ssh/sshsrv.c @@ -26,6 +26,7 @@ #include "responder/common/responder.h" #include "responder/ssh/sshsrv_private.h" #include "providers/data_provider.h" +#include "resolv/async_resolv.h" struct sbus_method monitor_ssh_methods[] = { { MON_CLI_METHOD_PING, monitor_common_pong }, @@ -128,6 +129,12 @@ int ssh_process_init(TALLOC_CTX *mem_ctx, ssh_dp_reconnect_init, iter); } + ret = resolv_init(ssh_ctx, ev, RESOLV_DEFAULT_TIMEOUT, &ssh_ctx->resolv); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, ("Could not set up resolver context\n")); + return ret; + } + DEBUG(SSSDBG_TRACE_FUNC, ("SSH Initialization complete\n")); return EOK; diff --git a/src/responder/ssh/sshsrv_cmd.c b/src/responder/ssh/sshsrv_cmd.c index 33f042a..be79f0c 100644 --- a/src/responder/ssh/sshsrv_cmd.c +++ b/src/responder/ssh/sshsrv_cmd.c @@ -33,6 +33,7 @@ #include "responder/common/responder.h" #include "responder/common/responder_packet.h" #include "responder/ssh/sshsrv_private.h" +#include "resolv/async_resolv.h" static errno_t ssh_cmd_parse_request(struct ssh_cmd_ctx *cmd_ctx); @@ -84,16 +85,16 @@ done: return ssh_cmd_done(cmd_ctx, ret); } -static errno_t -ssh_host_pubkeys_search(struct ssh_cmd_ctx *cmd_ctx); +static void +ssh_host_pubkeys_resolv_done(struct tevent_req *req); static int sss_ssh_cmd_get_host_pubkeys(struct cli_ctx *cctx) { + struct ssh_ctx *ssh_ctx = cctx->rctx->pvt_ctx; struct ssh_cmd_ctx *cmd_ctx; errno_t ret; - struct addrinfo ai_hint; - struct addrinfo *ai = NULL; + struct tevent_req *req; cmd_ctx = talloc_zero(cctx, struct ssh_cmd_ctx); if (!cmd_ctx) { @@ -111,27 +112,6 @@ 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); @@ -144,12 +124,54 @@ sss_ssh_cmd_get_host_pubkeys(struct cli_ctx *cctx) cmd_ctx->check_next = true; } - ret = ssh_host_pubkeys_search(cmd_ctx); + /* canonicalize host name */ + req = resolv_gethostbyname_send(cmd_ctx, cctx->rctx->ev, ssh_ctx->resolv, + cmd_ctx->name, IPV4_FIRST, + default_host_dbs); + if (!req) { + ret = ENOMEM; + DEBUG(SSSDBG_OP_FAILURE, + ("Out of memory sending resolver request\n")); + goto done; + } + + tevent_req_set_callback(req, ssh_host_pubkeys_resolv_done, cmd_ctx); + ret = EAGAIN; done: return ssh_cmd_done(cmd_ctx, ret); } +static errno_t +ssh_host_pubkeys_search(struct ssh_cmd_ctx *cmd_ctx); + +static void +ssh_host_pubkeys_resolv_done(struct tevent_req *req) +{ + struct ssh_cmd_ctx *cmd_ctx = tevent_req_callback_data(req, + struct ssh_cmd_ctx); + errno_t ret; + int resolv_status; + struct resolv_hostent *hostent; + + ret = resolv_gethostbyname_recv(req, cmd_ctx, + &resolv_status, NULL, &hostent); + talloc_zfree(req); + if (ret == EOK) { + if (strcmp(cmd_ctx->name, hostent->name) != 0) { + cmd_ctx->alias = cmd_ctx->name; + cmd_ctx->name = hostent->name; + } + } else { + DEBUG(SSSDBG_OP_FAILURE, + ("Failed to resolve [%s]: %s\n", cmd_ctx->name, + resolv_strerror(resolv_status))); + } + + ret = ssh_host_pubkeys_search(cmd_ctx); + ssh_cmd_done(cmd_ctx, ret); +} + static void ssh_dp_send_req_done(struct tevent_req *req) { diff --git a/src/responder/ssh/sshsrv_private.h b/src/responder/ssh/sshsrv_private.h index ab9edf7..315e4f2 100644 --- a/src/responder/ssh/sshsrv_private.h +++ b/src/responder/ssh/sshsrv_private.h @@ -31,6 +31,7 @@ struct ssh_ctx { struct resp_ctx *rctx; + struct resolv_ctx *resolv; }; struct ssh_cmd_ctx {