From be2d61c24cfa33bc082d17062239182edb386c4a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
Date: Thu, 12 Jul 2018 21:37:47 +0200
Subject: [PATCH 1/3] util: introduce sss_ssh_print_pubkey()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This function will be used to print the public keys, as already done in
sss_ssh_authorizedkeys.c.

Related:
https://pagure.io/SSSD/sssd/issue/3542

Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com>
---
 src/util/sss_ssh.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/util/sss_ssh.h |  3 +++
 2 files changed, 58 insertions(+)

diff --git a/src/util/sss_ssh.c b/src/util/sss_ssh.c
index a6709997a8..54886a094a 100644
--- a/src/util/sss_ssh.c
+++ b/src/util/sss_ssh.c
@@ -213,3 +213,58 @@ sss_ssh_format_pubkey(TALLOC_CTX *mem_ctx,
 
     return ret;
 }
+
+errno_t
+sss_ssh_print_pubkey(struct sss_ssh_pubkey *pubkey)
+{
+    TALLOC_CTX *tmp_ctx;
+    char *repr = NULL;
+    char *repr_break = NULL;
+    errno_t ret;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        return ENOMEM;
+    }
+
+    ret = sss_ssh_format_pubkey(tmp_ctx, pubkey, &repr);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE,
+              "sss_ssh_format_pubkey() failed (%d): %s\n",
+              ret, strerror(ret));
+        goto end;
+    }
+
+    /* OpenSSH expects a linebreak after each key */
+    repr_break = talloc_asprintf(tmp_ctx, "%s\n", repr);
+    talloc_zfree(repr);
+    if (repr_break == NULL) {
+        ret = ENOMEM;
+        goto end;
+    }
+
+    ret = sss_atomic_write_s(STDOUT_FILENO, repr_break, strlen(repr_break));
+    /* Avoid spiking memory with too many large keys */
+    talloc_zfree(repr_break);
+    if (ret < 0) {
+        ret = errno;
+        if (ret == EPIPE) {
+            DEBUG(SSSDBG_MINOR_FAILURE,
+                  "SSHD closed the pipe before all keys could be written\n");
+            /* Return 0 so that openssh doesn't abort pubkey auth */
+            ret = 0;
+            goto end;
+        }
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "sss_atomic_write_s() failed (%d): %s\n",
+              ret, strerror(ret));
+        goto end;
+    }
+
+    ret = EOK;
+
+ end:
+    talloc_zfree(tmp_ctx);
+
+    return ret;
+}
diff --git a/src/util/sss_ssh.h b/src/util/sss_ssh.h
index 1ba50a6552..d35ffb91e8 100644
--- a/src/util/sss_ssh.h
+++ b/src/util/sss_ssh.h
@@ -50,4 +50,7 @@ sss_ssh_format_pubkey(TALLOC_CTX *mem_ctx,
                       struct sss_ssh_pubkey *pubkey,
                       char **result);
 
+errno_t
+sss_ssh_print_pubkey(struct sss_ssh_pubkey *pubkey);
+
 #endif /* _SSS_SSH_H_ */

From f40c3a4d12b500c683fe032d6efb6313576136cc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
Date: Thu, 12 Jul 2018 21:56:29 +0200
Subject: [PATCH 2/3] ssh: make use of sss_ssh_print_pubkey()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Related:
https://pagure.io/SSSD/sssd/issue/3542

Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com>
---
 src/sss_client/ssh/sss_ssh_authorizedkeys.c | 35 +++--------------------------
 1 file changed, 3 insertions(+), 32 deletions(-)

diff --git a/src/sss_client/ssh/sss_ssh_authorizedkeys.c b/src/sss_client/ssh/sss_ssh_authorizedkeys.c
index b0280fbf8b..8e80f96636 100644
--- a/src/sss_client/ssh/sss_ssh_authorizedkeys.c
+++ b/src/sss_client/ssh/sss_ssh_authorizedkeys.c
@@ -46,7 +46,6 @@ int main(int argc, const char **argv)
     poptContext pc = NULL;
     struct sss_ssh_ent *ent;
     size_t i;
-    char *repr;
     int ret;
 
     debug_prg_name = argv[0];
@@ -108,38 +107,10 @@ int main(int argc, const char **argv)
 
     /* print results */
     for (i = 0; i < ent->num_pubkeys; i++) {
-        char *repr_break = NULL;
-
-        ret = sss_ssh_format_pubkey(mem_ctx, &ent->pubkeys[i], &repr);
-        if (ret != EOK) {
-            DEBUG(SSSDBG_OP_FAILURE,
-                  "sss_ssh_format_pubkey() failed (%d): %s\n",
-                    ret, strerror(ret));
-            continue;
-        }
-
-        /* OpenSSH expects a linebreak after each key */
-        repr_break = talloc_asprintf(mem_ctx, "%s\n", repr);
-        talloc_zfree(repr);
-        if (repr_break == NULL) {
-            ret = ENOMEM;
-            goto fini;
-        }
-
-        ret = sss_atomic_write_s(STDOUT_FILENO, repr_break, strlen(repr_break));
-        /* Avoid spiking memory with too many large keys */
-        talloc_zfree(repr_break);
-        if (ret < 0) {
-            ret = errno;
-            if (ret == EPIPE) {
-                DEBUG(SSSDBG_MINOR_FAILURE,
-                      "SSHD closed the pipe before all keys could be written\n");
-                /* Return 0 so that openssh doesn't abort pubkey auth */
-                ret = 0;
-                goto fini;
-            }
+        ret = sss_ssh_print_pubkey(&ent->pubkeys[i]);
+        if (ret != EOK && ret != EINVAL) {
             DEBUG(SSSDBG_CRIT_FAILURE,
-                  "sss_atomic_write_s() failed (%d): %s\n",
+                  "ssh_ssh_print_pubkey() failed (%d): %s\n",
                   ret, strerror(ret));
             goto fini;
         }

From 3ba5a7cb24ee0738231611532ddbe73874f6f569 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fabiano=20Fid=C3=AAncio?= <fidencio@redhat.com>
Date: Thu, 12 Jul 2018 22:01:14 +0200
Subject: [PATCH 3/3] sss_ssh_knownhostsproxy: add option to only print the
 pubkey
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Related:
https://pagure.io/SSSD/sssd/issue/3542

Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com>
---
 src/man/sss_ssh_knownhostsproxy.1.xml        | 10 ++++++++++
 src/sss_client/ssh/sss_ssh_knownhostsproxy.c | 24 +++++++++++++++++++++++-
 2 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/src/man/sss_ssh_knownhostsproxy.1.xml b/src/man/sss_ssh_knownhostsproxy.1.xml
index b71e1ea874..f84732c5de 100644
--- a/src/man/sss_ssh_knownhostsproxy.1.xml
+++ b/src/man/sss_ssh_knownhostsproxy.1.xml
@@ -84,6 +84,16 @@ GlobalKnownHostsFile /var/lib/sss/pubconf/known_hosts
                     </para>
                 </listitem>
             </varlistentry>
+            <varlistentry>
+                <term>
+                    <option>-k</option>,<option>--pubkeys</option>
+                </term>
+                <listitem>
+                    <para>
+                        Print the host ssh public keys for host <replaceable>HOST</replaceable>.
+                    </para>
+                </listitem>
+            </varlistentry>
             <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/param_help.xml" />
         </variablelist>
     </refsect1>
diff --git a/src/sss_client/ssh/sss_ssh_knownhostsproxy.c b/src/sss_client/ssh/sss_ssh_knownhostsproxy.c
index 976ba86b32..9e574adea4 100644
--- a/src/sss_client/ssh/sss_ssh_knownhostsproxy.c
+++ b/src/sss_client/ssh/sss_ssh_knownhostsproxy.c
@@ -197,6 +197,7 @@ int main(int argc, const char **argv)
     const char *pc_domain = NULL;
     const char *pc_host = NULL;
     const char **pc_args = NULL;
+    int pc_pubkeys = 0;
     struct poptOption long_options[] = {
         POPT_AUTOHELP
         { "debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_debug, 0,
@@ -205,6 +206,8 @@ int main(int argc, const char **argv)
           _("The port to use to connect to the host"), NULL },
         { "domain", 'd', POPT_ARG_STRING, &pc_domain, 0,
           _("The SSSD domain to use"), NULL },
+        { "pubkey", 'k', POPT_ARG_NONE, &pc_pubkeys, 0,
+          _("Print the host ssh public keys"), NULL },
         POPT_TABLEEND
     };
     poptContext pc = NULL;
@@ -213,7 +216,7 @@ int main(int argc, const char **argv)
     struct addrinfo *ai = NULL;
     char canonhost[NI_MAXHOST];
     const char *host = NULL;
-    struct sss_ssh_ent *ent;
+    struct sss_ssh_ent *ent = NULL;
     int ret;
 
     debug_prg_name = argv[0];
@@ -302,6 +305,25 @@ int main(int argc, const char **argv)
         }
     }
 
+    if (pc_pubkeys) {
+        /* print results */
+        if (ent != NULL) {
+            for (size_t i = 0; i < ent->num_pubkeys; i++) {
+                ret = sss_ssh_print_pubkey(&ent->pubkeys[i]);
+                if (ret != EOK && ret != EINVAL) {
+                    DEBUG(SSSDBG_CRIT_FAILURE,
+                          "ssh_ssh_print_pubkey() failed (%d): %s\n",
+                          ret, strerror(ret));
+                    ret = EXIT_FAILURE;
+                    goto fini;
+                }
+            }
+        }
+
+        ret = EXIT_SUCCESS;
+        goto fini;
+    }
+
     /* connect to server */
     if (pc_args) {
         ret = connect_proxy_command(discard_const(pc_args));
