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