summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Cholasta <jcholast@redhat.com>2012-04-18 07:05:29 -0400
committerStephen Gallagher <sgallagh@redhat.com>2012-04-24 09:50:56 -0400
commit4fa3ef8d8a8a3cddf8025d306c3b90b37dd431bc (patch)
tree34d80280cfa9ae80139808f6af0df6f668f8ed4e
parentb35f20cd8ecdc8308a3201e55752fb0443ec6ae4 (diff)
downloadsssd-4fa3ef8d8a8a3cddf8025d306c3b90b37dd431bc.tar.gz
sssd-4fa3ef8d8a8a3cddf8025d306c3b90b37dd431bc.tar.bz2
sssd-4fa3ef8d8a8a3cddf8025d306c3b90b37dd431bc.zip
SSH: Add support for hashed known_hosts
https://fedorahosted.org/sssd/ticket/1203
-rw-r--r--src/confdb/confdb.h2
-rw-r--r--src/config/SSSDConfig.py3
-rw-r--r--src/config/etc/sssd.api.conf1
-rw-r--r--src/man/sssd.conf.5.xml25
-rw-r--r--src/responder/ssh/sshsrv.c13
-rw-r--r--src/responder/ssh/sshsrv_cmd.c192
-rw-r--r--src/responder/ssh/sshsrv_private.h2
-rw-r--r--src/sss_client/ssh/sss_ssh_authorizedkeys.c2
-rw-r--r--src/util/sss_ssh.c9
-rw-r--r--src/util/sss_ssh.h3
10 files changed, 212 insertions, 40 deletions
diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index 78e37510..b90db303 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -109,6 +109,8 @@
/* SSH */
#define CONFDB_SSH_CONF_ENTRY "config/ssh"
+#define CONFDB_SSH_HASH_KNOWN_HOSTS "ssh_hash_known_hosts"
+#define CONFDB_DEFAULT_SSH_HASH_KNOWN_HOSTS true
/* Data Provider */
#define CONFDB_DP_CONF_ENTRY "config/dp"
diff --git a/src/config/SSSDConfig.py b/src/config/SSSDConfig.py
index 20cd2a28..d38014c2 100644
--- a/src/config/SSSDConfig.py
+++ b/src/config/SSSDConfig.py
@@ -82,6 +82,9 @@ option_strings = {
# [autofs]
'autofs_negative_timeout' : _('Negative cache timeout length (seconds)'),
+ # [ssh]
+ 'ssh_hash_known_hosts': _('Whether to hash host names and adresses in the known_hosts file'),
+
# [provider]
'id_provider' : _('Identity provider'),
'auth_provider' : _('Authentication provider'),
diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf
index 17750ef9..a7bece99 100644
--- a/src/config/etc/sssd.api.conf
+++ b/src/config/etc/sssd.api.conf
@@ -58,6 +58,7 @@ autofs_negative_timeout = int, None, false
[ssh]
# ssh service
+ssh_hash_known_hosts = bool, None, false
[provider]
#Available provider types
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index 43eb3632..ef7490d9 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -729,6 +729,31 @@
</variablelist>
</refsect2>
+ <refsect2 id='SSH' condition="with_ssh">
+ <title>SSH configuration options</title>
+ <para>
+ These options can be used to configure the SSH service.
+ </para>
+ <para>
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/experimental.xml" />
+ </para>
+
+ <variablelist>
+ <varlistentry>
+ <term>ssh_hash_known_hosts (bool)</term>
+ <listitem>
+ <para>
+ Whether or not to hash host names and adresses in
+ the managed known_hosts file.
+ </para>
+ <para>
+ Default: true
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsect2>
+
</refsect1>
<refsect1 id='domain-sections'>
diff --git a/src/responder/ssh/sshsrv.c b/src/responder/ssh/sshsrv.c
index f0cee9f0..a423231b 100644
--- a/src/responder/ssh/sshsrv.c
+++ b/src/responder/ssh/sshsrv.c
@@ -128,6 +128,19 @@ int ssh_process_init(TALLOC_CTX *mem_ctx,
ssh_dp_reconnect_init, iter);
}
+ /* Get responder options */
+
+ /* Get ssh_hash_known_hosts option */
+ ret = confdb_get_bool(ssh_ctx->rctx->cdb,
+ CONFDB_SSH_CONF_ENTRY, CONFDB_SSH_HASH_KNOWN_HOSTS,
+ CONFDB_DEFAULT_SSH_HASH_KNOWN_HOSTS,
+ &ssh_ctx->hash_known_hosts);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE, ("Error reading from confdb (%d) [%s]\n",
+ ret, strerror(ret)));
+ 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 91b888ef..4766ed8b 100644
--- a/src/responder/ssh/sshsrv_cmd.c
+++ b/src/responder/ssh/sshsrv_cmd.c
@@ -417,6 +417,139 @@ ssh_host_pubkeys_search_dp_callback(uint16_t err_maj,
ssh_cmd_done(cmd_ctx, ret);
}
+static char *
+ssh_host_pubkeys_format_known_host_plain(TALLOC_CTX *mem_ctx,
+ struct sss_ssh_ent *ent)
+{
+ TALLOC_CTX *tmp_ctx;
+ char *name, *pubkey, *result;
+ size_t i;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return NULL;
+ }
+
+ name = talloc_strdup(tmp_ctx, ent->name);
+ if (!name) {
+ goto done;
+ }
+
+ for (i = 0; i < ent->num_aliases; i++) {
+ name = talloc_asprintf_append(name, ",%s", ent->aliases[i]);
+ if (!name) {
+ goto done;
+ }
+ }
+
+ result = talloc_strdup(tmp_ctx, "");
+ if (!result) {
+ goto done;
+ }
+
+ for (i = 0; i < ent->num_pubkeys; i++) {
+ pubkey = sss_ssh_format_pubkey(tmp_ctx, ent, &ent->pubkeys[i],
+ SSS_SSH_FORMAT_OPENSSH, "");
+ if (!pubkey) {
+ result = NULL;
+ goto done;
+ }
+
+ result = talloc_asprintf_append(result, "%s %s\n", name, pubkey);
+ if (!result) {
+ goto done;
+ }
+
+ talloc_free(pubkey);
+ }
+
+ talloc_steal(mem_ctx, result);
+
+done:
+ talloc_free(tmp_ctx);
+
+ return result;
+}
+
+static char *
+ssh_host_pubkeys_format_known_host_hashed(TALLOC_CTX *mem_ctx,
+ struct sss_ssh_ent *ent)
+{
+ TALLOC_CTX *tmp_ctx;
+ errno_t ret;
+ char *name, *pubkey, *saltstr, *hashstr, *result;
+ unsigned char salt[SSS_SHA1_LENGTH], hash[SSS_SHA1_LENGTH];
+ size_t i, j, k;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return NULL;
+ }
+
+ result = talloc_strdup(tmp_ctx, "");
+ if (!result) {
+ goto done;
+ }
+
+ for (i = 0; i < ent->num_pubkeys; i++) {
+ pubkey = sss_ssh_format_pubkey(tmp_ctx, ent, &ent->pubkeys[i],
+ SSS_SSH_FORMAT_OPENSSH, "");
+ if (!pubkey) {
+ result = NULL;
+ goto done;
+ }
+
+ for (j = 0; j <= ent->num_aliases; j++) {
+ name = (j == 0 ? ent->name : ent->aliases[j-1]);
+
+ for (k = 0; k < SSS_SHA1_LENGTH; k++) {
+ salt[k] = rand();
+ }
+
+ ret = sss_hmac_sha1(salt, SSS_SHA1_LENGTH,
+ (unsigned char *)name, strlen(name),
+ hash);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("sss_hmac_sha1() failed (%d): %s\n",
+ ret, strerror(ret)));
+ result = NULL;
+ goto done;
+ }
+
+ saltstr = sss_base64_encode(tmp_ctx, salt, SSS_SHA1_LENGTH);
+ if (!saltstr) {
+ result = NULL;
+ goto done;
+ }
+
+ hashstr = sss_base64_encode(tmp_ctx, hash, SSS_SHA1_LENGTH);
+ if (!hashstr) {
+ result = NULL;
+ goto done;
+ }
+
+ result = talloc_asprintf_append(result, "|1|%s|%s %s\n",
+ saltstr, hashstr, pubkey);
+ if (!result) {
+ goto done;
+ }
+
+ talloc_free(saltstr);
+ talloc_free(hashstr);
+ }
+
+ talloc_free(pubkey);
+ }
+
+ talloc_steal(mem_ctx, result);
+
+done:
+ talloc_free(tmp_ctx);
+
+ return result;
+}
+
static errno_t
ssh_host_pubkeys_update_known_hosts(struct ssh_cmd_ctx *cmd_ctx)
{
@@ -430,12 +563,13 @@ ssh_host_pubkeys_update_known_hosts(struct ssh_cmd_ctx *cmd_ctx)
};
struct cli_ctx *cctx = cmd_ctx->cctx;
struct sss_domain_info *dom = cctx->rctx->domains;
+ struct ssh_ctx *ssh_ctx = (struct ssh_ctx *)cctx->rctx->pvt_ctx;
struct sysdb_ctx *sysdb;
struct ldb_message **hosts;
- size_t num_hosts, i, j, k;
+ size_t num_hosts, i;
struct sss_ssh_ent *ent;
int fd = -1;
- char *filename, *pubkey, *line;
+ char *filename, *entstr;
ssize_t wret;
mode_t old_mask;
@@ -487,43 +621,29 @@ ssh_host_pubkeys_update_known_hosts(struct ssh_cmd_ctx *cmd_ctx)
continue;
}
- for (j = 0; j < ent->num_pubkeys; j++) {
- pubkey = sss_ssh_format_pubkey(tmp_ctx, ent, &ent->pubkeys[j],
- SSS_SSH_FORMAT_OPENSSH);
- if (!pubkey) {
- DEBUG(SSSDBG_OP_FAILURE,
- ("Out of memory formatting SSH public key\n"));
- continue;
- }
-
- line = talloc_strdup(tmp_ctx, ent->name);
- if (!line) {
- ret = ENOMEM;
- goto done;
- }
-
- for (k = 0; k < ent->num_aliases; k++) {
- line = talloc_asprintf_append(line, ",%s", ent->aliases[k]);
- if (!line) {
- ret = ENOMEM;
- goto done;
- }
- }
-
- line = talloc_asprintf_append(line, " %s\n", pubkey);
- if (!line) {
- ret = ENOMEM;
- goto done;
- }
-
- wret = sss_atomic_write_s(fd, line, strlen(line));
- if (wret == -1) {
- ret = errno;
- goto done;
- }
+ if (ssh_ctx->hash_known_hosts) {
+ entstr = ssh_host_pubkeys_format_known_host_hashed(ent, ent);
+ } else {
+ entstr = ssh_host_pubkeys_format_known_host_plain(ent, ent);
+ }
+ if (!entstr) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Failed to format known_hosts data for [%s]\n",
+ ent->name));
+ continue;
}
+
+ wret = sss_atomic_write_s(fd, entstr, strlen(entstr));
+ if (wret == -1) {
+ ret = errno;
+ goto done;
+ }
+
+ talloc_free(ent);
}
+ talloc_free(hosts);
+
dom = dom->next;
}
diff --git a/src/responder/ssh/sshsrv_private.h b/src/responder/ssh/sshsrv_private.h
index ab9edf7c..d74b4925 100644
--- a/src/responder/ssh/sshsrv_private.h
+++ b/src/responder/ssh/sshsrv_private.h
@@ -31,6 +31,8 @@
struct ssh_ctx {
struct resp_ctx *rctx;
+
+ bool hash_known_hosts;
};
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 b64bbc3d..dd9a0628 100644
--- a/src/sss_client/ssh/sss_ssh_authorizedkeys.c
+++ b/src/sss_client/ssh/sss_ssh_authorizedkeys.c
@@ -110,7 +110,7 @@ int main(int argc, const char **argv)
/* print results */
for (i = 0; i < ent->num_pubkeys; i++) {
repr = sss_ssh_format_pubkey(mem_ctx, ent, &ent->pubkeys[i],
- SSS_SSH_FORMAT_OPENSSH);
+ SSS_SSH_FORMAT_OPENSSH, NULL);
if (!repr) {
ERROR("Not enough memory\n");
ret = EXIT_FAILURE;
diff --git a/src/util/sss_ssh.c b/src/util/sss_ssh.c
index 0163c1d8..60ed5878 100644
--- a/src/util/sss_ssh.c
+++ b/src/util/sss_ssh.c
@@ -136,13 +136,18 @@ char *
sss_ssh_format_pubkey(TALLOC_CTX *mem_ctx,
struct sss_ssh_ent *ent,
struct sss_ssh_pubkey *pubkey,
- enum sss_ssh_pubkey_format format)
+ enum sss_ssh_pubkey_format format,
+ const char *comment)
{
TALLOC_CTX *tmp_ctx;
char *blob;
char *algo;
char *result = NULL;
+ if (!comment) {
+ comment = ent->name;
+ }
+
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) {
return NULL;
@@ -166,7 +171,7 @@ sss_ssh_format_pubkey(TALLOC_CTX *mem_ctx,
goto done;
}
- result = talloc_asprintf(mem_ctx, "%s %s %s", algo, blob, ent->name);
+ result = talloc_asprintf(mem_ctx, "%s %s %s", algo, blob, comment);
break;
}
diff --git a/src/util/sss_ssh.h b/src/util/sss_ssh.h
index a4ac7391..29743a08 100644
--- a/src/util/sss_ssh.h
+++ b/src/util/sss_ssh.h
@@ -54,6 +54,7 @@ char *
sss_ssh_format_pubkey(TALLOC_CTX *mem_ctx,
struct sss_ssh_ent *ent,
struct sss_ssh_pubkey *pubkey,
- enum sss_ssh_pubkey_format format);
+ enum sss_ssh_pubkey_format format,
+ const char *comment);
#endif /* _SSS_SSH_H_ */