Blame SOURCES/0062-Views-apply-user-SSH-public-key-override.patch

905b4d
From a5a3aaafd0c1399f83bd3144344eb9a0da436307 Mon Sep 17 00:00:00 2001
905b4d
From: Sumit Bose <sbose@redhat.com>
905b4d
Date: Thu, 16 Oct 2014 13:17:37 +0200
905b4d
Subject: [PATCH 62/64] Views: apply user SSH public key override
905b4d
905b4d
With this patch the SSH public key override attribute is read from the
905b4d
FreeIPA server and saved in the cache with the other override data.
905b4d
905b4d
Since it is possible to have multiple public SSH keys this override
905b4d
value does not replace any other data but will be added to existing
905b4d
values.
905b4d
905b4d
Fixes https://fedorahosted.org/sssd/ticket/2454
905b4d
905b4d
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
905b4d
---
905b4d
 src/db/sysdb_views.c           |  38 +++++++++----
905b4d
 src/man/sssd-ipa.5.xml         |   3 +
905b4d
 src/providers/ipa/ipa_common.h |   1 +
905b4d
 src/providers/ipa/ipa_opts.h   |   1 +
905b4d
 src/responder/ssh/sshsrv_cmd.c | 123 +++++++++++++++++++++++++++++++----------
905b4d
 5 files changed, 126 insertions(+), 40 deletions(-)
905b4d
905b4d
diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c
905b4d
index f2cf370231b57c3cd2b563eec4ea2a0f3a0935bd..27b58701fe0f9a4f545df5e4bfb884c04517d0d3 100644
905b4d
--- a/src/db/sysdb_views.c
905b4d
+++ b/src/db/sysdb_views.c
905b4d
@@ -560,6 +560,8 @@ errno_t sysdb_apply_default_override(struct sss_domain_info *domain,
905b4d
     TALLOC_CTX *tmp_ctx;
905b4d
     struct sysdb_attrs *attrs;
905b4d
     size_t c;
905b4d
+    size_t d;
905b4d
+    size_t num_values;
905b4d
     struct ldb_message_element *el = NULL;
905b4d
     const char *allowed_attrs[] = { SYSDB_UIDNUM,
905b4d
                                     SYSDB_GIDNUM,
905b4d
@@ -567,6 +569,7 @@ errno_t sysdb_apply_default_override(struct sss_domain_info *domain,
905b4d
                                     SYSDB_HOMEDIR,
905b4d
                                     SYSDB_SHELL,
905b4d
                                     SYSDB_NAME,
905b4d
+                                    SYSDB_SSH_PUBKEY,
905b4d
                                     NULL };
905b4d
     bool override_attrs_found = false;
905b4d
 
905b4d
@@ -584,7 +587,6 @@ errno_t sysdb_apply_default_override(struct sss_domain_info *domain,
905b4d
     }
905b4d
 
905b4d
     for (c = 0; allowed_attrs[c] != NULL; c++) {
905b4d
-        /* TODO: add nameAlias for case-insentitive searches */
905b4d
         ret = sysdb_attrs_get_el_ext(override_attrs, allowed_attrs[c], false,
905b4d
                                      &el);
905b4d
         if (ret == EOK) {
905b4d
@@ -607,17 +609,30 @@ errno_t sysdb_apply_default_override(struct sss_domain_info *domain,
905b4d
                     goto done;
905b4d
                 }
905b4d
             } else {
905b4d
-                ret = sysdb_attrs_add_val(attrs,  allowed_attrs[c],
905b4d
-                                          &el->values[0]);
905b4d
-                if (ret != EOK) {
905b4d
-                    DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_val failed.\n");
905b4d
-                    goto done;
905b4d
+                num_values = el->num_values;
905b4d
+                /* Only SYSDB_SSH_PUBKEY is allowed to have multiple values. */
905b4d
+                if (strcmp(allowed_attrs[c], SYSDB_SSH_PUBKEY) != 0
905b4d
+                        && num_values != 1) {
905b4d
+                    DEBUG(SSSDBG_MINOR_FAILURE,
905b4d
+                          "Override attribute for [%s] has more [%zd] " \
905b4d
+                          "than one value, using only the first.\n",
905b4d
+                          allowed_attrs[c], num_values);
905b4d
+                    num_values = 1;
905b4d
+                }
905b4d
+
905b4d
+                for (d = 0; d < num_values; d++) {
905b4d
+                    ret = sysdb_attrs_add_val(attrs,  allowed_attrs[c],
905b4d
+                                              &el->values[d]);
905b4d
+                    if (ret != EOK) {
905b4d
+                        DEBUG(SSSDBG_OP_FAILURE,
905b4d
+                              "sysdb_attrs_add_val failed.\n");
905b4d
+                        goto done;
905b4d
+                    }
905b4d
+                    DEBUG(SSSDBG_TRACE_ALL,
905b4d
+                          "Override [%s] with [%.*s] for [%s].\n",
905b4d
+                          allowed_attrs[c], (int) el->values[d].length,
905b4d
+                          el->values[d].data, ldb_dn_get_linearized(obj_dn));
905b4d
                 }
905b4d
-                DEBUG(SSSDBG_TRACE_ALL, "Override [%s] with [%.*s] for [%s].\n",
905b4d
-                                        allowed_attrs[c],
905b4d
-                                        (int) el->values[0].length,
905b4d
-                                        el->values[0].data,
905b4d
-                                        ldb_dn_get_linearized(obj_dn));
905b4d
             }
905b4d
         } else if (ret != ENOENT) {
905b4d
             DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_el_ext failed.\n");
905b4d
@@ -983,6 +998,7 @@ errno_t sysdb_add_overrides_to_object(struct sss_domain_info *domain,
905b4d
         {SYSDB_HOMEDIR, OVERRIDE_PREFIX SYSDB_HOMEDIR},
905b4d
         {SYSDB_SHELL, OVERRIDE_PREFIX SYSDB_SHELL},
905b4d
         {SYSDB_NAME, OVERRIDE_PREFIX SYSDB_NAME},
905b4d
+        {SYSDB_SSH_PUBKEY, OVERRIDE_PREFIX SYSDB_SSH_PUBKEY},
905b4d
         {NULL, NULL}
905b4d
     };
905b4d
     size_t c;
905b4d
diff --git a/src/man/sssd-ipa.5.xml b/src/man/sssd-ipa.5.xml
905b4d
index 51f14f8fc16bd2843ef4b426938172c63608176e..e8a716c4104b8038e354b8ae544a04d6773e708b 100644
905b4d
--- a/src/man/sssd-ipa.5.xml
905b4d
+++ b/src/man/sssd-ipa.5.xml
905b4d
@@ -626,6 +626,9 @@
905b4d
                                     <listitem>
905b4d
                                         <para>ldap_user_shell</para>
905b4d
                                     </listitem>
905b4d
+                                    <listitem>
905b4d
+                                        <para>ldap_user_ssh_public_key</para>
905b4d
+                                    </listitem>
905b4d
                                 </itemizedlist>
905b4d
                             </para>
905b4d
                             <para>
905b4d
diff --git a/src/providers/ipa/ipa_common.h b/src/providers/ipa/ipa_common.h
905b4d
index 0e9324f5b362085153abebcc4894bef607173607..495276548e57e91f9744dda6d8866971b627b4da 100644
905b4d
--- a/src/providers/ipa/ipa_common.h
905b4d
+++ b/src/providers/ipa/ipa_common.h
905b4d
@@ -128,6 +128,7 @@ enum ipa_override_attrs {
905b4d
     IPA_AT_OVERRIDE_SHELL,
905b4d
     IPA_AT_OVERRIDE_GROUP_NAME,
905b4d
     IPA_AT_OVERRIDE_GROUP_GID_NUMBER,
905b4d
+    IPA_AT_OVERRIDE_USER_SSH_PUBLIC_KEY,
905b4d
 
905b4d
     IPA_OPTS_OVERRIDE
905b4d
 };
905b4d
diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
905b4d
index 0e0eed49cd397fe88ce7bf41579c066088947d04..473eca4f77727e008663d082e954820a9fb0c427 100644
905b4d
--- a/src/providers/ipa/ipa_opts.h
905b4d
+++ b/src/providers/ipa/ipa_opts.h
905b4d
@@ -283,6 +283,7 @@ struct sdap_attr_map ipa_override_map[] = {
905b4d
     { "ldap_user_shell", "loginShell", SYSDB_SHELL, NULL },
905b4d
     { "ldap_group_name", "cn", SYSDB_NAME, NULL },
905b4d
     { "ldap_group_gid_number", "gidNumber", SYSDB_GIDNUM, NULL },
905b4d
+    { "ldap_user_ssh_public_key", "ipaSshPubKey", SYSDB_SSH_PUBKEY, NULL },
905b4d
     SDAP_ATTR_MAP_TERMINATOR
905b4d
 };
905b4d
 
905b4d
diff --git a/src/responder/ssh/sshsrv_cmd.c b/src/responder/ssh/sshsrv_cmd.c
905b4d
index ad831639841d42417008ea6c40c1dea045e5d6cf..5bed2e0adca0e6961337bb744729dd3e5a23c629 100644
905b4d
--- a/src/responder/ssh/sshsrv_cmd.c
905b4d
+++ b/src/responder/ssh/sshsrv_cmd.c
905b4d
@@ -232,8 +232,8 @@ ssh_user_pubkeys_search_next(struct ssh_cmd_ctx *cmd_ctx)
905b4d
         return EFAULT;
905b4d
     }
905b4d
 
905b4d
-    ret = sysdb_get_user_attr(cmd_ctx, cmd_ctx->domain,
905b4d
-                              cmd_ctx->name, attrs, &res;;
905b4d
+    ret = sysdb_get_user_attr_with_views(cmd_ctx, cmd_ctx->domain,
905b4d
+                                         cmd_ctx->name, attrs, &res;;
905b4d
     if (ret != EOK) {
905b4d
         DEBUG(SSSDBG_CRIT_FAILURE,
905b4d
               "Failed to make request to our cache!\n");
905b4d
@@ -782,6 +782,65 @@ ssh_cmd_parse_request(struct ssh_cmd_ctx *cmd_ctx)
905b4d
     return EOK;
905b4d
 }
905b4d
 
905b4d
+static errno_t decode_and_add_base64_data(struct ssh_cmd_ctx *cmd_ctx,
905b4d
+                                          struct ldb_message_element *el,
905b4d
+                                          size_t fqname_len,
905b4d
+                                          const char *fqname,
905b4d
+                                          size_t *c)
905b4d
+{
905b4d
+    struct cli_ctx *cctx = cmd_ctx->cctx;
905b4d
+    uint8_t *key;
905b4d
+    size_t key_len;
905b4d
+    uint8_t *body;
905b4d
+    size_t body_len;
905b4d
+    int ret;
905b4d
+    size_t d;
905b4d
+    TALLOC_CTX *tmp_ctx;
905b4d
+
905b4d
+    if (el == NULL) {
905b4d
+        DEBUG(SSSDBG_TRACE_ALL, "Mssing element, nothing to do.\n");
905b4d
+        return EOK;
905b4d
+    }
905b4d
+
905b4d
+    tmp_ctx = talloc_new(NULL);
905b4d
+    if (tmp_ctx == NULL) {
905b4d
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
905b4d
+        return ENOMEM;
905b4d
+    }
905b4d
+
905b4d
+    for (d = 0; d < el->num_values; d++) {
905b4d
+        key = sss_base64_decode(tmp_ctx, (const char *) el->values[d].data,
905b4d
+                                &key_len);
905b4d
+        if (key == NULL) {
905b4d
+            DEBUG(SSSDBG_OP_FAILURE, "sss_base64_decode failed.\n");
905b4d
+            ret = ENOMEM;
905b4d
+            goto done;
905b4d
+        }
905b4d
+
905b4d
+        ret = sss_packet_grow(cctx->creq->out,
905b4d
+                              3*sizeof(uint32_t) + key_len + fqname_len);
905b4d
+        if (ret != EOK) {
905b4d
+            DEBUG(SSSDBG_OP_FAILURE, "sss_packet_grow failed.\n");
905b4d
+            goto done;
905b4d
+        }
905b4d
+        sss_packet_get_body(cctx->creq->out, &body, &body_len);
905b4d
+
905b4d
+        SAFEALIGN_SET_UINT32(body+(*c), 0, c);
905b4d
+        SAFEALIGN_SET_UINT32(body+(*c), fqname_len, c);
905b4d
+        safealign_memcpy(body+(*c), fqname, fqname_len, c);
905b4d
+        SAFEALIGN_SET_UINT32(body+(*c), key_len, c);
905b4d
+        safealign_memcpy(body+(*c), key, key_len, c);
905b4d
+
905b4d
+    }
905b4d
+
905b4d
+    ret = EOK;
905b4d
+
905b4d
+done:
905b4d
+    talloc_free(tmp_ctx);
905b4d
+
905b4d
+    return ret;
905b4d
+}
905b4d
+
905b4d
 static errno_t
905b4d
 ssh_cmd_build_reply(struct ssh_cmd_ctx *cmd_ctx)
905b4d
 {
905b4d
@@ -790,14 +849,13 @@ ssh_cmd_build_reply(struct ssh_cmd_ctx *cmd_ctx)
905b4d
     uint8_t *body;
905b4d
     size_t body_len;
905b4d
     size_t c = 0;
905b4d
-    unsigned int i;
905b4d
-    struct ldb_message_element *el;
905b4d
+    struct ldb_message_element *el = NULL;
905b4d
+    struct ldb_message_element *el_override = NULL;
905b4d
+    struct ldb_message_element *el_orig = NULL;
905b4d
     uint32_t count = 0;
905b4d
     const char *name;
905b4d
     char *fqname;
905b4d
     uint32_t fqname_len;
905b4d
-    uint8_t *key;
905b4d
-    size_t key_len;
905b4d
 
905b4d
     ret = sss_packet_new(cctx->creq, 0,
905b4d
                          sss_packet_get_cmd(cctx->creq->in),
905b4d
@@ -811,6 +869,20 @@ ssh_cmd_build_reply(struct ssh_cmd_ctx *cmd_ctx)
905b4d
         count = el->num_values;
905b4d
     }
905b4d
 
905b4d
+    el_orig = ldb_msg_find_element(cmd_ctx->result,
905b4d
+                                  ORIGINALAD_PREFIX SYSDB_SSH_PUBKEY);
905b4d
+    if (el_orig) {
905b4d
+        count = el_orig->num_values;
905b4d
+    }
905b4d
+
905b4d
+    if (DOM_HAS_VIEWS(cmd_ctx->domain)) {
905b4d
+        el_override = ldb_msg_find_element(cmd_ctx->result,
905b4d
+                                           OVERRIDE_PREFIX SYSDB_SSH_PUBKEY);
905b4d
+        if (el_override) {
905b4d
+            count += el_override->num_values;
905b4d
+        }
905b4d
+    }
905b4d
+
905b4d
     ret = sss_packet_grow(cctx->creq->out, 2*sizeof(uint32_t));
905b4d
     if (ret != EOK) {
905b4d
         return ret;
905b4d
@@ -820,7 +892,7 @@ ssh_cmd_build_reply(struct ssh_cmd_ctx *cmd_ctx)
905b4d
     SAFEALIGN_SET_UINT32(body+c, count, &c);
905b4d
     SAFEALIGN_SET_UINT32(body+c, 0, &c);
905b4d
 
905b4d
-    if (!el) {
905b4d
+    if (count == 0) {
905b4d
         return EOK;
905b4d
     }
905b4d
 
905b4d
@@ -840,30 +912,23 @@ ssh_cmd_build_reply(struct ssh_cmd_ctx *cmd_ctx)
905b4d
 
905b4d
     fqname_len = strlen(fqname)+1;
905b4d
 
905b4d
-    for (i = 0; i < el->num_values; i++) {
905b4d
-        key = sss_base64_decode(cmd_ctx,
905b4d
-                                (const char *)el->values[i].data,
905b4d
-                                &key_len);
905b4d
-        if (!key) {
905b4d
-            return ENOMEM;
905b4d
-        }
905b4d
+    ret = decode_and_add_base64_data(cmd_ctx, el, fqname_len, fqname, &c);
905b4d
+    if (ret != EOK) {
905b4d
+        DEBUG(SSSDBG_OP_FAILURE, "decode_and_add_base64_data failed.\n");
905b4d
+        return ret;
905b4d
+    }
905b4d
 
905b4d
-        ret = sss_packet_grow(cctx->creq->out,
905b4d
-                              3*sizeof(uint32_t) + key_len + fqname_len);
905b4d
-        if (ret != EOK) {
905b4d
-            talloc_free(key);
905b4d
-            return ret;
905b4d
-        }
905b4d
-        sss_packet_get_body(cctx->creq->out, &body, &body_len);
905b4d
+    ret = decode_and_add_base64_data(cmd_ctx, el_orig, fqname_len, fqname, &c);
905b4d
+    if (ret != EOK) {
905b4d
+        DEBUG(SSSDBG_OP_FAILURE, "decode_and_add_base64_data failed.\n");
905b4d
+        return ret;
905b4d
+    }
905b4d
 
905b4d
-        SAFEALIGN_SET_UINT32(body+c, 0, &c);
905b4d
-        SAFEALIGN_SET_UINT32(body+c, fqname_len, &c);
905b4d
-        safealign_memcpy(body+c, fqname, fqname_len, &c);
905b4d
-        SAFEALIGN_SET_UINT32(body+c, key_len, &c);
905b4d
-        safealign_memcpy(body+c, key, key_len, &c);
905b4d
-
905b4d
-        talloc_free(key);
905b4d
-        count++;
905b4d
+    ret = decode_and_add_base64_data(cmd_ctx, el_override, fqname_len, fqname,
905b4d
+                                     &c);
905b4d
+    if (ret != EOK) {
905b4d
+        DEBUG(SSSDBG_OP_FAILURE, "decode_and_add_base64_data failed.\n");
905b4d
+        return ret;
905b4d
     }
905b4d
 
905b4d
     return EOK;
905b4d
-- 
905b4d
1.9.3
905b4d