>From c1ecc51ae96f60a82b1f57f7484d0bee02b7787c Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jcholast@redhat.com>
Date: Wed, 14 Mar 2012 07:54:16 -0400
Subject: [PATCH 1/2] SSH: Allow clients to explicitly specify host alias

This change removes the need to canonicalize host names on the responder
side - the relevant code was removed.
---
 Makefile.am                                  |    4 +-
 src/responder/ssh/sshsrv.c                   |    7 --
 src/responder/ssh/sshsrv_cmd.c               |   96 ++++++++++----------------
 src/responder/ssh/sshsrv_private.h           |    1 -
 src/sss_client/ssh/sss_ssh_authorizedkeys.c  |    9 ++-
 src/sss_client/ssh/sss_ssh_client.c          |   18 +++++-
 src/sss_client/ssh/sss_ssh_client.h          |    1 +
 src/sss_client/ssh/sss_ssh_knownhostsproxy.c |    3 +-
 8 files changed, 63 insertions(+), 76 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 64f5c42..c298556 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -534,11 +534,9 @@ if BUILD_SSH
 sssd_ssh_SOURCES = \
     src/responder/ssh/sshsrv.c \
     src/responder/ssh/sshsrv_cmd.c \
-    $(SSSD_RESPONDER_OBJ) \
-    $(SSSD_RESOLV_OBJ)
+    $(SSSD_RESPONDER_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 8e979a7..f0cee9f 100644
--- a/src/responder/ssh/sshsrv.c
+++ b/src/responder/ssh/sshsrv.c
@@ -26,7 +26,6 @@
 #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 },
@@ -129,12 +128,6 @@ 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 4494917..5d72907 100644
--- a/src/responder/ssh/sshsrv_cmd.c
+++ b/src/responder/ssh/sshsrv_cmd.c
@@ -33,7 +33,6 @@
 #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);
@@ -85,16 +84,14 @@ done:
     return ssh_cmd_done(cmd_ctx, ret);
 }
 
-static void
-ssh_host_pubkeys_resolv_done(struct tevent_req *req);
+static errno_t
+ssh_host_pubkeys_search(struct ssh_cmd_ctx *cmd_ctx);
 
 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 tevent_req *req;
+    struct ssh_cmd_ctx *cmd_ctx;
 
     cmd_ctx = talloc_zero(cctx, struct ssh_cmd_ctx);
     if (!cmd_ctx) {
@@ -109,8 +106,9 @@ sss_ssh_cmd_get_host_pubkeys(struct cli_ctx *cctx)
     }
 
     DEBUG(SSSDBG_TRACE_FUNC,
-          ("Requesting SSH host public keys for [%s] from [%s]\n",
-           cmd_ctx->name, cmd_ctx->domname ? cmd_ctx->domname : "<ALL>"));
+          ("Requesting SSH host public keys for [%s][%s] from [%s]\n",
+           cmd_ctx->name, cmd_ctx->alias ? cmd_ctx->alias : "",
+           cmd_ctx->domname ? cmd_ctx->domname : "<ALL>"));
 
     if (cmd_ctx->domname) {
         cmd_ctx->domain = responder_get_domain(cctx->rctx->domains,
@@ -124,54 +122,12 @@ sss_ssh_cmd_get_host_pubkeys(struct cli_ctx *cctx)
         cmd_ctx->check_next = true;
     }
 
-    /* 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;
+    ret = ssh_host_pubkeys_search(cmd_ctx);
 
 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)
 {
@@ -601,28 +557,30 @@ ssh_cmd_parse_request(struct ssh_cmd_ctx *cmd_ctx)
     uint8_t *body;
     size_t body_len;
     size_t c = 0;
-    uint32_t reserved;
+    uint32_t flags;
     uint32_t name_len;
     char *name;
+    uint32_t alias_len;
+    char *alias;
 
     sss_packet_get_body(cctx->creq->in, &body, &body_len);
 
-    SAFEALIGN_COPY_UINT32_CHECK(&reserved, body+c, body_len, &c);
-    if (reserved != 0) {
+    SAFEALIGN_COPY_UINT32_CHECK(&flags, body+c, body_len, &c);
+    if (flags > 1) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid flags received [0x%x]\n", flags));
         return EINVAL;
     }
 
     SAFEALIGN_COPY_UINT32_CHECK(&name_len, body+c, body_len, &c);
     if (name_len == 0) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Zero-length name is not valid\n"));
         return EINVAL;
     }
 
     name = (char *)(body+c);
-    if (!sss_utf8_check((const uint8_t *)name, name_len-1)) {
-        DEBUG(SSSDBG_CRIT_FAILURE, ("Supplied data is not valid UTF-8 string\n"));
-        return EINVAL;
-    }
-    if (strnlen(name, name_len) != name_len-1) {
+    if (!sss_utf8_check((const uint8_t *)name, name_len-1) ||
+            name[name_len-1] != 0) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("Name is not valid UTF-8 string\n"));
         return EINVAL;
     }
     c += name_len;
@@ -634,6 +592,26 @@ ssh_cmd_parse_request(struct ssh_cmd_ctx *cmd_ctx)
         return ENOENT;
     }
 
+    if (flags & 1) {
+        SAFEALIGN_COPY_UINT32_CHECK(&alias_len, body+c, body_len, &c);
+        if (alias_len == 0) {
+            DEBUG(SSSDBG_CRIT_FAILURE, ("Zero-length alias is not valid\n"));
+            return EINVAL;
+        }
+
+        alias = (char *)(body+c);
+        if (!sss_utf8_check((const uint8_t *)alias, alias_len-1) ||
+                alias[alias_len-1] != 0) {
+            DEBUG(SSSDBG_CRIT_FAILURE, ("Alias is not valid UTF-8 string\n"));
+            return EINVAL;
+        }
+        c += alias_len;
+
+        if (strcmp(cmd_ctx->name, alias) != 0) {
+            cmd_ctx->alias = talloc_strdup(cmd_ctx, alias);
+        }
+    }
+
     return EOK;
 }
 
diff --git a/src/responder/ssh/sshsrv_private.h b/src/responder/ssh/sshsrv_private.h
index 315e4f2..ab9edf7 100644
--- a/src/responder/ssh/sshsrv_private.h
+++ b/src/responder/ssh/sshsrv_private.h
@@ -31,7 +31,6 @@
 
 struct ssh_ctx {
     struct resp_ctx *rctx;
-    struct resolv_ctx *resolv;
 };
 
 struct ssh_cmd_ctx {
diff --git a/src/sss_client/ssh/sss_ssh_authorizedkeys.c b/src/sss_client/ssh/sss_ssh_authorizedkeys.c
index 174cb53..b64bbc3 100644
--- a/src/sss_client/ssh/sss_ssh_authorizedkeys.c
+++ b/src/sss_client/ssh/sss_ssh_authorizedkeys.c
@@ -97,7 +97,8 @@ int main(int argc, const char **argv)
     }
 
     /* look up public keys */
-    ret = sss_ssh_get_ent(mem_ctx, SSS_SSH_GET_USER_PUBKEYS, user, &ent);
+    ret = sss_ssh_get_ent(mem_ctx, SSS_SSH_GET_USER_PUBKEYS,
+                          user, NULL, &ent);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE,
               ("sss_ssh_get_ent() failed (%d): %s\n", ret, strerror(ret)));
@@ -111,9 +112,9 @@ int main(int argc, const char **argv)
         repr = sss_ssh_format_pubkey(mem_ctx, ent, &ent->pubkeys[i],
                                      SSS_SSH_FORMAT_OPENSSH);
         if (!repr) {
-            DEBUG(SSSDBG_OP_FAILURE,
-                  ("Out of memory formatting SSH public key\n"));
-            continue;
+            ERROR("Not enough memory\n");
+            ret = EXIT_FAILURE;
+            goto fini;
         }
 
         printf("%s\n", repr);
diff --git a/src/sss_client/ssh/sss_ssh_client.c b/src/sss_client/ssh/sss_ssh_client.c
index 41b20e7..8520cd1 100644
--- a/src/sss_client/ssh/sss_ssh_client.c
+++ b/src/sss_client/ssh/sss_ssh_client.c
@@ -70,9 +70,13 @@ int set_locale(void)
 
 /* SSH public key request:
  * 
- * 0..3:     flags (unsigned int, must be 0)
+ * 0..3:     flags (unsigned int, must be 0 or 1)
  * 4..7:     name length (unsigned int)
  * 8..(X-1): name (null-terminated UTF-8 string)
+ * if (flags & 1) {
+ *   X..(X+3): alias length (unsigned int)
+ *   (X+4)..Y: alias (null-terminated UTF-8 string)
+ * }
  * 
  * SSH public key reply:
  * 
@@ -89,6 +93,7 @@ errno_t
 sss_ssh_get_ent(TALLOC_CTX *mem_ctx,
                 enum sss_cli_command command,
                 const char *name,
+                const char *alias,
                 struct sss_ssh_ent **result)
 {
     TALLOC_CTX *tmp_ctx;
@@ -96,6 +101,7 @@ sss_ssh_get_ent(TALLOC_CTX *mem_ctx,
     errno_t ret;
     uint32_t flags;
     uint32_t name_len;
+    uint32_t alias_len;
     size_t req_len;
     uint8_t *req = NULL;
     size_t c = 0;
@@ -115,6 +121,12 @@ sss_ssh_get_ent(TALLOC_CTX *mem_ctx,
     name_len = strlen(name)+1;
     req_len = 2*sizeof(uint32_t) + name_len;
 
+    if (alias) {
+        flags |= 1;
+        alias_len = strlen(alias)+1;
+        req_len += sizeof(uint32_t) + alias_len;
+    }
+
     req = talloc_array(tmp_ctx, uint8_t, req_len);
     if (!req) {
         ret = ENOMEM;
@@ -124,6 +136,10 @@ sss_ssh_get_ent(TALLOC_CTX *mem_ctx,
     SAFEALIGN_SET_UINT32(req+c, flags, &c);
     SAFEALIGN_SET_UINT32(req+c, name_len, &c);
     safealign_memcpy(req+c, name, name_len, &c);
+    if (alias) {
+        SAFEALIGN_SET_UINT32(req+c, alias_len, &c);
+        safealign_memcpy(req+c, alias, alias_len, &c);
+    }
 
     /* send request */
     rd.data = req;
diff --git a/src/sss_client/ssh/sss_ssh_client.h b/src/sss_client/ssh/sss_ssh_client.h
index 1c8db1f..7ffc398 100644
--- a/src/sss_client/ssh/sss_ssh_client.h
+++ b/src/sss_client/ssh/sss_ssh_client.h
@@ -34,6 +34,7 @@ errno_t
 sss_ssh_get_ent(TALLOC_CTX *mem_ctx,
                 enum sss_cli_command command,
                 const char *name,
+                const char *alias,
                 struct sss_ssh_ent **result);
 
 #endif /* _SSS_SSH_CLIENT_H_ */
diff --git a/src/sss_client/ssh/sss_ssh_knownhostsproxy.c b/src/sss_client/ssh/sss_ssh_knownhostsproxy.c
index 280532b..19206c3 100644
--- a/src/sss_client/ssh/sss_ssh_knownhostsproxy.c
+++ b/src/sss_client/ssh/sss_ssh_knownhostsproxy.c
@@ -275,7 +275,8 @@ int main(int argc, const char **argv)
     }
 
     /* look up public keys */
-    ret = sss_ssh_get_ent(mem_ctx, SSS_SSH_GET_HOST_PUBKEYS, host, &ent);
+    ret = sss_ssh_get_ent(mem_ctx, SSS_SSH_GET_HOST_PUBKEYS,
+                          host, NULL, &ent);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE,
               ("sss_ssh_get_ent() failed (%d): %s\n", ret, strerror(ret)));
-- 
1.7.7.6

