Update SSSD for the F19 test day

- Explicitly Require libini_config >= 1.0.0.1 to work around a SONAME bug in ding-libs
- Fix SSH integration with fully-qualified domains
- Add the ability to dynamically discover the NetBIOS name
This commit is contained in:
Jakub Hrozek 2013-05-07 10:44:52 +02:00
parent 3726d5f5e7
commit 14fef6c6d9
7 changed files with 1448 additions and 1 deletions

View File

@ -0,0 +1,702 @@
From 4cdaf239d4504966bed8ecd5e3fa07def74c7302 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Thu, 2 May 2013 20:28:30 +0200
Subject: [PATCH 1/6] AD: read flat name and SID of the AD domain
For various features either the flat/short/NetBIOS domain name or the
domain SID is needed. Since the responders already try to do a subdomain
lookup when and known domain name is encountered I added a subdomain
lookup to the AD provider which currently only reads the SID from the
base DN and the NetBIOS name from a reply of a LDAP ping. The results
are written to the cache to have them available even if SSSD is started
in offline mode. Looking up trusted domains can be added later.
Since all the needed responder code is already available from the
corresponding work for the IPA provider this patch fixes
https://fedorahosted.org/sssd/ticket/1468
---
Makefile.am | 2 +
src/config/etc/sssd.api.d/sssd-ad.conf | 2 +
src/man/sssd-ad.5.xml | 4 +
src/man/sssd.conf.5.xml | 4 +
src/providers/ad/ad_init.c | 31 ++
src/providers/ad/ad_subdomains.c | 522 +++++++++++++++++++++++++++++++++
src/providers/ad/ad_subdomains.h | 37 +++
7 files changed, 602 insertions(+)
create mode 100644 src/providers/ad/ad_subdomains.c
create mode 100644 src/providers/ad/ad_subdomains.h
diff --git a/Makefile.am b/Makefile.am
index 3abea76c18f49df623ff9c38ebc5d604596d2516..b72384a77fe5bb3d2d40229026c463fefabc1387 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1621,6 +1621,8 @@ libsss_ad_la_SOURCES = \
src/providers/ad/ad_access.h \
src/providers/ad/ad_opts.h \
src/providers/ad/ad_srv.c \
+ src/providers/ad/ad_subdomains.c \
+ src/providers/ad/ad_subdomains.h \
src/util/find_uid.c \
src/util/user_info_msg.c \
src/util/sss_krb5.c \
diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf
index b4b1d0ba11d600a8b9a300f15cc8058be470f422..3be25e8da05ee6b1bbdb947e919421358591cdde 100644
--- a/src/config/etc/sssd.api.d/sssd-ad.conf
+++ b/src/config/etc/sssd.api.d/sssd-ad.conf
@@ -126,3 +126,5 @@ krb5_use_enterprise_principal = bool, None, false
[provider/ad/chpass]
krb5_kpasswd = str, None, false
krb5_backup_kpasswd = str, None, false
+
+[provider/ad/subdomains]
diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml
index c19607715dafd39f167c3066831ae7ad09ffe459..4dcd552d7f1fe3235af9c582c49c553441a014e9 100644
--- a/src/man/sssd-ad.5.xml
+++ b/src/man/sssd-ad.5.xml
@@ -95,6 +95,10 @@ ldap_id_mapping = False
specified as the lower-case version of the long
version of the Active Directory domain.
</para>
+ <para>
+ The short domain name (also known as the NetBIOS
+ or the flat name) is autodetected by the SSSD.
+ </para>
</listitem>
</varlistentry>
diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
index 04c699948b093c235762c0d9f8223911a6fd2ada..99337fbba9fb8d39a62eb84313c5b89761ee950d 100644
--- a/src/man/sssd.conf.5.xml
+++ b/src/man/sssd.conf.5.xml
@@ -1481,6 +1481,10 @@ override_homedir = /home/%u
Regular expression for this domain that describes
how to parse the string containing user name and
domain into these components.
+ The "domain" can match either the SSSD
+ configuration domain name, or, in the case
+ of IPA trust subdomains and Active Directory
+ domains, the flat (NetBIOS) name of the domain.
</para>
<para>
Default for the AD and IPA provider:
diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c
index 2f5a5da1510b0241a4bee12fc93da174fdd0d116..f90df2a6913222b023704e9e1d1dce9561772e98 100644
--- a/src/providers/ad/ad_init.c
+++ b/src/providers/ad/ad_init.c
@@ -37,6 +37,7 @@
#include "providers/ad/ad_id.h"
#include "providers/ad/ad_srv.h"
#include "providers/dp_dyndns.h"
+#include "providers/ad/ad_subdomains.h"
struct ad_options *ad_options = NULL;
@@ -361,3 +362,33 @@ ad_shutdown(struct be_req *req)
/* TODO: Clean up any internal data */
sdap_handler_done(req, DP_ERR_OK, EOK, NULL);
}
+
+int sssm_ad_subdomains_init(struct be_ctx *bectx,
+ struct bet_ops **ops,
+ void **pvt_data)
+{
+ int ret;
+ struct ad_id_ctx *id_ctx;
+ const char *ad_domain;
+
+ ret = sssm_ad_id_init(bectx, ops, (void **) &id_ctx);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("sssm_ad_id_init failed.\n"));
+ return ret;
+ }
+
+ if (ad_options == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Global AD options not available.\n"));
+ return EINVAL;
+ }
+
+ ad_domain = dp_opt_get_string(ad_options->basic, AD_DOMAIN);
+
+ ret = ad_subdom_init(bectx, id_ctx, ad_domain, ops, pvt_data);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("ad_subdom_init failed.\n"));
+ return ret;
+ }
+
+ return EOK;
+}
diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
new file mode 100644
index 0000000000000000000000000000000000000000..1da343f8711b2b99a7afff6a4a398a1aa515a875
--- /dev/null
+++ b/src/providers/ad/ad_subdomains.c
@@ -0,0 +1,522 @@
+/*
+ SSSD
+
+ AD Subdomains Module
+
+ Authors:
+ Sumit Bose <sbose@redhat.com>
+
+ Copyright (C) 2013 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "providers/ldap/sdap_async.h"
+#include "providers/ad/ad_subdomains.h"
+#include <ctype.h>
+#include <ndr.h>
+#include <ndr/ndr_nbt.h>
+
+#define AD_AT_OBJECT_SID "objectSID"
+#define AD_AT_DNS_DOMAIN "DnsDomain"
+#define AD_AT_NT_VERSION "NtVer"
+#define AD_AT_NETLOGON "netlogon"
+
+#define MASTER_DOMAIN_SID_FILTER "objectclass=domain"
+
+/* do not refresh more often than every 5 seconds for now */
+#define AD_SUBDOMAIN_REFRESH_LIMIT 5
+
+/* refresh automatically every 4 hours */
+#define AD_SUBDOMAIN_REFRESH_PERIOD (3600 * 4)
+
+struct ad_subdomains_ctx {
+ struct be_ctx *be_ctx;
+ struct sdap_id_ctx *sdap_id_ctx;
+ struct sss_idmap_ctx *idmap_ctx;
+ char *domain_name;
+
+ time_t last_refreshed;
+ struct tevent_timer *timer_event;
+};
+
+struct ad_subdomains_req_ctx {
+ struct be_req *be_req;
+ struct ad_subdomains_ctx *sd_ctx;
+ struct sdap_id_op *sdap_op;
+
+ char *current_filter;
+ size_t base_iter;
+
+ size_t reply_count;
+ struct sysdb_attrs **reply;
+
+ char *master_sid;
+ char *flat_name;
+};
+
+static void ad_subdomains_get_conn_done(struct tevent_req *req);
+static errno_t ad_subdomains_get_master_sid(struct ad_subdomains_req_ctx *ctx);
+static void ad_subdomains_get_master_sid_done(struct tevent_req *req);
+static void ad_subdomains_get_netlogon_done(struct tevent_req *req);
+
+static void ad_subdomains_retrieve(struct ad_subdomains_ctx *ctx,
+ struct be_req *be_req)
+{
+ struct ad_subdomains_req_ctx *req_ctx = NULL;
+ struct tevent_req *req;
+ int dp_error = DP_ERR_FATAL;
+ int ret;
+
+ req_ctx = talloc(be_req, struct ad_subdomains_req_ctx);
+ if (req_ctx == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ req_ctx->be_req = be_req;
+ req_ctx->sd_ctx = ctx;
+ req_ctx->current_filter = NULL;
+ req_ctx->base_iter = 0;
+ req_ctx->reply_count = 0;
+ req_ctx->reply = NULL;
+
+ req_ctx->sdap_op = sdap_id_op_create(req_ctx,
+ ctx->sdap_id_ctx->conn_cache);
+ if (req_ctx->sdap_op == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sdap_id_op_create failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ req = sdap_id_op_connect_send(req_ctx->sdap_op, req_ctx, &ret);
+ if (req == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sdap_id_op_connect_send failed: %d(%s).\n",
+ ret, strerror(ret)));
+ goto done;
+ }
+
+ tevent_req_set_callback(req, ad_subdomains_get_conn_done, req_ctx);
+
+ return;
+
+done:
+ talloc_free(req_ctx);
+ if (ret == EOK) {
+ dp_error = DP_ERR_OK;
+ }
+ be_req_terminate(be_req, dp_error, ret, NULL);
+}
+
+static void ad_subdomains_get_conn_done(struct tevent_req *req)
+{
+ int ret;
+ int dp_error = DP_ERR_FATAL;
+ struct ad_subdomains_req_ctx *ctx;
+
+ ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
+
+ ret = sdap_id_op_connect_recv(req, &dp_error);
+ talloc_zfree(req);
+ if (ret) {
+ if (dp_error == DP_ERR_OFFLINE) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ ("No AD server is available, cannot get the "
+ "subdomain list while offline\n"));
+ } else {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Failed to connect to AD server: [%d](%s)\n",
+ ret, strerror(ret)));
+ }
+
+ goto fail;
+ }
+
+ ret = ad_subdomains_get_master_sid(ctx);
+ if (ret == EAGAIN) {
+ return;
+ } else if (ret != EOK) {
+ goto fail;
+ }
+
+ DEBUG(SSSDBG_OP_FAILURE, ("No search base available.\n"));
+ ret = EINVAL;
+
+fail:
+ be_req_terminate(ctx->be_req, dp_error, ret, NULL);
+}
+
+static errno_t ad_subdomains_get_master_sid(struct ad_subdomains_req_ctx *ctx)
+{
+ struct tevent_req *req;
+ struct sdap_search_base *base;
+ const char *master_sid_attrs[] = {AD_AT_OBJECT_SID, NULL};
+
+
+ base = ctx->sd_ctx->sdap_id_ctx->opts->search_bases[ctx->base_iter];
+ if (base == NULL) {
+ return EOK;
+ }
+
+ req = sdap_get_generic_send(ctx, ctx->sd_ctx->be_ctx->ev,
+ ctx->sd_ctx->sdap_id_ctx->opts,
+ sdap_id_op_handle(ctx->sdap_op),
+ base->basedn, LDAP_SCOPE_BASE,
+ MASTER_DOMAIN_SID_FILTER, master_sid_attrs,
+ NULL, 0,
+ dp_opt_get_int(ctx->sd_ctx->sdap_id_ctx->opts->basic,
+ SDAP_SEARCH_TIMEOUT),
+ false);
+
+ if (req == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sdap_get_generic_send failed.\n"));
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(req, ad_subdomains_get_master_sid_done, ctx);
+
+ return EAGAIN;
+}
+
+static void ad_subdomains_get_master_sid_done(struct tevent_req *req)
+{
+ int ret;
+ size_t reply_count;
+ struct sysdb_attrs **reply = NULL;
+ struct ad_subdomains_req_ctx *ctx;
+ struct ldb_message_element *el;
+ char *sid_str;
+ enum idmap_error_code err;
+ static const char *attrs[] = {AD_AT_NETLOGON, NULL};
+ char *filter;
+ char *ntver;
+
+ ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
+
+ ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply);
+ talloc_zfree(req);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sdap_get_generic_send request failed.\n"));
+ goto done;
+ }
+
+ if (reply_count == 0) {
+ ctx->base_iter++;
+ ret = ad_subdomains_get_master_sid(ctx);
+ if (ret == EAGAIN) {
+ return;
+ } else if (ret != EOK) {
+ goto done;
+ }
+ } else if (reply_count == 1) {
+ ret = sysdb_attrs_get_el(reply[0], AD_AT_OBJECT_SID, &el);
+ if (ret != EOK || el->num_values != 1) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sdap_attrs_get_el failed.\n"));
+ goto done;
+ }
+
+ err = sss_idmap_bin_sid_to_sid(ctx->sd_ctx->idmap_ctx,
+ el->values[0].data,
+ el->values[0].length,
+ &sid_str);
+ if (err != IDMAP_SUCCESS) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ ("Could not convert SID: [%s].\n", idmap_error_string(err)));
+ ret = EFAULT;
+ goto done;
+ }
+
+ ctx->master_sid = talloc_steal(ctx, sid_str);
+ } else {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("More than one result for domain SID found.\n"));
+ ret = EINVAL;
+ goto done;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, ("Found SID [%s].\n", ctx->master_sid));
+
+ ntver = sss_ldap_encode_ndr_uint32(ctx, NETLOGON_NT_VERSION_5EX |
+ NETLOGON_NT_VERSION_WITH_CLOSEST_SITE);
+ if (ntver == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sss_ldap_encode_ndr_uint32 failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ filter = talloc_asprintf(ctx, "(&(%s=%s)(%s=%s))",
+ AD_AT_DNS_DOMAIN, ctx->sd_ctx->domain_name,
+ AD_AT_NT_VERSION, ntver);
+ if (filter == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_asprintf failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ req = sdap_get_generic_send(ctx, ctx->sd_ctx->be_ctx->ev,
+ ctx->sd_ctx->sdap_id_ctx->opts,
+ sdap_id_op_handle(ctx->sdap_op),
+ "", LDAP_SCOPE_BASE, filter, attrs, NULL, 0,
+ dp_opt_get_int(ctx->sd_ctx->sdap_id_ctx->opts->basic,
+ SDAP_SEARCH_TIMEOUT),
+ false);
+ if (req == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sdap_get_generic_send failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(req, ad_subdomains_get_netlogon_done, ctx);
+ return;
+
+done:
+ be_req_terminate(ctx->be_req, DP_ERR_FATAL, ret, NULL);
+}
+
+static void ad_subdomains_get_netlogon_done(struct tevent_req *req)
+{
+ int ret;
+ size_t reply_count;
+ struct sysdb_attrs **reply = NULL;
+ struct ad_subdomains_req_ctx *ctx;
+ struct ldb_message_element *el;
+ DATA_BLOB blob;
+ enum ndr_err_code ndr_err;
+ struct ndr_pull *ndr_pull = NULL;
+ struct netlogon_samlogon_response response;
+
+ ctx = tevent_req_callback_data(req, struct ad_subdomains_req_ctx);
+
+ ret = sdap_get_generic_recv(req, ctx, &reply_count, &reply);
+ talloc_zfree(req);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sdap_get_generic_send request failed.\n"));
+ goto done;
+ }
+
+ if (reply_count == 0) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("No netlogon data available.\n"));
+ } else if (reply_count > 1) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("More than one netlogon info returned.\n"));
+ ret = EINVAL;
+ goto done;
+ }
+
+ ret = sysdb_attrs_get_el(reply[0], AD_AT_NETLOGON, &el);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("sysdb_attrs_get_el() failed\n"));
+ goto done;
+ }
+
+ if (el->num_values == 0) {
+ DEBUG(SSSDBG_OP_FAILURE, ("netlogon has no value\n"));
+ ret = ENOENT;
+ goto done;
+ } else if (el->num_values > 1) {
+ DEBUG(SSSDBG_OP_FAILURE, ("More than one netlogon value?\n"));
+ ret = EIO;
+ goto done;
+ }
+
+ blob.data = el->values[0].data;
+ blob.length = el->values[0].length;
+
+ ndr_pull = ndr_pull_init_blob(&blob, ctx);
+ if (ndr_pull == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("ndr_pull_init_blob() failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ndr_err = ndr_pull_netlogon_samlogon_response(ndr_pull, NDR_SCALARS,
+ &response);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(SSSDBG_OP_FAILURE, ("ndr_pull_netlogon_samlogon_response() "
+ "failed [%d]\n", ndr_err));
+ ret = EBADMSG;
+ goto done;
+ }
+
+ if (!(response.ntver & NETLOGON_NT_VERSION_5EX)) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Wrong version returned [%x]\n",
+ response.ntver));
+ ret = EBADMSG;
+ goto done;
+ }
+
+ if (response.data.nt5_ex.domain_name != NULL &&
+ *response.data.nt5_ex.domain_name != '\0') {
+ ctx->flat_name = talloc_strdup(ctx, response.data.nt5_ex.domain_name);
+ if (ctx->flat_name == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC, ("Found flat name [%s].\n", ctx->flat_name));
+
+ ret = sysdb_master_domain_add_info(ctx->sd_ctx->be_ctx->domain,
+ NULL, ctx->flat_name, ctx->master_sid);
+
+ ret = EOK;
+
+done:
+
+ if (ret == EOK) {
+ ctx->sd_ctx->last_refreshed = time(NULL);
+ }
+ be_req_terminate(ctx->be_req, DP_ERR_FATAL, ret, NULL);
+}
+
+static void ad_subdom_online_cb(void *pvt);
+
+static void ad_subdom_timer_refresh(struct tevent_context *ev,
+ struct tevent_timer *te,
+ struct timeval current_time,
+ void *pvt)
+{
+ ad_subdom_online_cb(pvt);
+}
+
+static void ad_subdom_be_req_callback(struct be_req *be_req,
+ int dp_err, int dp_ret,
+ const char *errstr)
+{
+ talloc_free(be_req);
+}
+
+static void ad_subdom_online_cb(void *pvt)
+{
+ struct ad_subdomains_ctx *ctx;
+ struct be_req *be_req;
+ struct timeval tv;
+
+ ctx = talloc_get_type(pvt, struct ad_subdomains_ctx);
+ if (!ctx) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Bad private pointer\n"));
+ return;
+ }
+
+ be_req = be_req_create(ctx, NULL, ctx->be_ctx,
+ ad_subdom_be_req_callback, NULL);
+ if (be_req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("be_req_create() failed.\n"));
+ return;
+ }
+
+ ad_subdomains_retrieve(ctx, be_req);
+
+ tv = tevent_timeval_current_ofs(AD_SUBDOMAIN_REFRESH_PERIOD, 0);
+ ctx->timer_event = tevent_add_timer(ctx->be_ctx->ev, ctx, tv,
+ ad_subdom_timer_refresh, ctx);
+ if (!ctx->timer_event) {
+ DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to add subdom timer event\n"));
+ }
+}
+
+static void ad_subdom_offline_cb(void *pvt)
+{
+ struct ad_subdomains_ctx *ctx;
+
+ ctx = talloc_get_type(pvt, struct ad_subdomains_ctx);
+
+ if (ctx) {
+ talloc_zfree(ctx->timer_event);
+ }
+}
+
+void ad_subdomains_handler(struct be_req *be_req)
+{
+ struct be_ctx *be_ctx = be_req_get_be_ctx(be_req);
+ struct ad_subdomains_ctx *ctx;
+ time_t now;
+
+ ctx = talloc_get_type(be_ctx->bet_info[BET_SUBDOMAINS].pvt_bet_data,
+ struct ad_subdomains_ctx);
+ if (!ctx) {
+ be_req_terminate(be_req, DP_ERR_FATAL, EINVAL, NULL);
+ return;
+ }
+
+ now = time(NULL);
+
+ if (ctx->last_refreshed > now - AD_SUBDOMAIN_REFRESH_LIMIT) {
+ be_req_terminate(be_req, DP_ERR_OK, EOK, NULL);
+ return;
+ }
+
+ ad_subdomains_retrieve(ctx, be_req);
+}
+
+struct bet_ops ad_subdomains_ops = {
+ .handler = ad_subdomains_handler,
+ .finalize = NULL
+};
+
+static void *idmap_talloc(size_t size, void *pvt)
+{
+ return talloc_size(pvt, size);
+}
+
+static void idmap_free(void *ptr, void *pvt)
+{
+ talloc_free(ptr);
+}
+
+int ad_subdom_init(struct be_ctx *be_ctx,
+ struct ad_id_ctx *id_ctx,
+ const char *ad_domain,
+ struct bet_ops **ops,
+ void **pvt_data)
+{
+ struct ad_subdomains_ctx *ctx;
+ int ret;
+ enum idmap_error_code err;
+
+ ctx = talloc_zero(id_ctx, struct ad_subdomains_ctx);
+ if (ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_zero failed.\n"));
+ return ENOMEM;
+ }
+
+ ctx->be_ctx = be_ctx;
+ ctx->sdap_id_ctx = id_ctx->sdap_id_ctx;
+ ctx->domain_name = talloc_strdup(ctx, ad_domain);
+ if (ctx->domain_name == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n"));
+ return ENOMEM;
+ }
+ *ops = &ad_subdomains_ops;
+ *pvt_data = ctx;
+
+ ret = be_add_online_cb(ctx, be_ctx, ad_subdom_online_cb, ctx, NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to add subdom online callback"));
+ }
+
+ ret = be_add_offline_cb(ctx, be_ctx, ad_subdom_offline_cb, ctx, NULL);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_MINOR_FAILURE, ("Failed to add subdom offline callback"));
+ }
+
+ err = sss_idmap_init(idmap_talloc, ctx, idmap_free, &ctx->idmap_ctx);
+ if (err != IDMAP_SUCCESS) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to initialize idmap context.\n"));
+ return EFAULT;
+ }
+
+ return EOK;
+}
diff --git a/src/providers/ad/ad_subdomains.h b/src/providers/ad/ad_subdomains.h
new file mode 100644
index 0000000000000000000000000000000000000000..b1a418f132595c10abd8448f78a5df62402314a8
--- /dev/null
+++ b/src/providers/ad/ad_subdomains.h
@@ -0,0 +1,37 @@
+/*
+ SSSD
+
+ AD Subdomains Module
+
+ Authors:
+ Sumit Bose <sbose@redhat.com>
+
+ Copyright (C) 2013 Red Hat
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _IPA_SUBDOMAINS_H_
+#define _IPA_SUBDOMAINS_H_
+
+#include "providers/dp_backend.h"
+#include "providers/ad/ad_common.h"
+
+int ad_subdom_init(struct be_ctx *be_ctx,
+ struct ad_id_ctx *id_ctx,
+ const char *ad_domain,
+ struct bet_ops **ops,
+ void **pvt_data);
+
+#endif /* _IPA_SUBDOMAINS_H_ */
--
1.8.2.1

View File

@ -0,0 +1,65 @@
From 7c091610f5b35e8ba89da839322f6591f1e7619b Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek@redhat.com>
Date: Mon, 6 May 2013 15:10:22 +0200
Subject: [PATCH 2/6] Actually use the index parameter in
resolv_get_sockaddr_address_index
---
src/resolv/async_resolv.c | 11 +++++++----
src/resolv/async_resolv.h | 5 +++--
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/src/resolv/async_resolv.c b/src/resolv/async_resolv.c
index 1eb0acf83cb5bb48d92a58b8baf872f4ca4d8278..ad9d58297d0701e2a48ef86179c93c71320654fb 100644
--- a/src/resolv/async_resolv.c
+++ b/src/resolv/async_resolv.c
@@ -1453,8 +1453,9 @@ resolv_get_string_ptr_address(TALLOC_CTX *mem_ctx,
}
struct sockaddr_storage *
-resolv_get_sockaddr_address_index(TALLOC_CTX *mem_ctx, struct resolv_hostent *hostent,
- int port, int index)
+resolv_get_sockaddr_address_index(TALLOC_CTX *mem_ctx,
+ struct resolv_hostent *hostent,
+ int port, int addrindex)
{
struct sockaddr_storage *sockaddr;
@@ -1470,14 +1471,16 @@ resolv_get_sockaddr_address_index(TALLOC_CTX *mem_ctx, struct resolv_hostent *ho
case AF_INET:
sockaddr->ss_family = AF_INET;
memcpy(&((struct sockaddr_in *) sockaddr)->sin_addr,
- hostent->addr_list[0]->ipaddr, sizeof(struct in_addr));
+ hostent->addr_list[addrindex]->ipaddr,
+ sizeof(struct in_addr));
((struct sockaddr_in *) sockaddr)->sin_port = (in_port_t) htons(port);
break;
case AF_INET6:
sockaddr->ss_family = AF_INET6;
memcpy(&((struct sockaddr_in6 *) sockaddr)->sin6_addr,
- hostent->addr_list[0]->ipaddr, sizeof(struct in6_addr));
+ hostent->addr_list[addrindex]->ipaddr,
+ sizeof(struct in6_addr));
((struct sockaddr_in6 *) sockaddr)->sin6_port = (in_port_t) htons(port);
break;
default:
diff --git a/src/resolv/async_resolv.h b/src/resolv/async_resolv.h
index 9bf5e0c40e44c385858fa4d85adebe6e022ca006..a8207884c79d7a12af2bc1fc9da9c1304b2c252d 100644
--- a/src/resolv/async_resolv.h
+++ b/src/resolv/async_resolv.h
@@ -129,8 +129,9 @@ resolv_get_string_ptr_address(TALLOC_CTX *mem_ctx,
resolv_get_string_address_index(mem_ctx, hostent, 0)
struct sockaddr_storage *
-resolv_get_sockaddr_address_index(TALLOC_CTX *mem_ctx, struct resolv_hostent *hostent,
- int port, int index);
+resolv_get_sockaddr_address_index(TALLOC_CTX *mem_ctx,
+ struct resolv_hostent *hostent,
+ int port, int addrindex);
#define resolv_get_sockaddr_address(mem_ctx, rhostent, port) \
resolv_get_sockaddr_address_index(mem_ctx, rhostent, port, 0)
--
1.8.2.1

View File

@ -0,0 +1,205 @@
From f54b271376b23cb968eafb9ffd5100c6dadad2a7 Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jcholast@redhat.com>
Date: Fri, 26 Apr 2013 09:40:53 +0200
Subject: [PATCH 3/6] UTIL: Add function sss_names_init_from_args
This function allows initializing sss_names_ctx using a regular expression and
fully qualified format string specified in its arguments.
---
src/util/usertools.c | 107 +++++++++++++++++++++++++++++++--------------------
src/util/util.h | 7 ++++
2 files changed, 73 insertions(+), 41 deletions(-)
diff --git a/src/util/usertools.c b/src/util/usertools.c
index 7323d9f8260580f32b4ab55c8c2db5bd7eec20ed..91110f263657de9ba53ed305e7c4710eb006bec6 100644
--- a/src/util/usertools.c
+++ b/src/util/usertools.c
@@ -135,13 +135,11 @@ done:
#endif
}
-int sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb,
- const char *domain, struct sss_names_ctx **out)
+int sss_names_init_from_args(TALLOC_CTX *mem_ctx, const char *re_pattern,
+ const char *fq_fmt, struct sss_names_ctx **out)
{
struct sss_names_ctx *ctx;
- TALLOC_CTX *tmpctx = NULL;
const char *errstr;
- char *conf_path;
int errval;
int errpos;
int ret;
@@ -150,6 +148,49 @@ int sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb,
if (!ctx) return ENOMEM;
talloc_set_destructor(ctx, sss_names_ctx_destructor);
+ ctx->re_pattern = talloc_strdup(ctx, re_pattern);
+ if (ctx->re_pattern == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ DEBUG(SSSDBG_CONF_SETTINGS, ("Using re [%s].\n", ctx->re_pattern));
+
+ ctx->fq_fmt = talloc_strdup(ctx, fq_fmt);
+ if (ctx->fq_fmt == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ctx->re = pcre_compile2(ctx->re_pattern,
+ NAME_DOMAIN_PATTERN_OPTIONS,
+ &errval, &errstr, &errpos, NULL);
+ if (!ctx->re) {
+ DEBUG(1, ("Invalid Regular Expression pattern at position %d."
+ " (Error: %d [%s])\n", errpos, errval, errstr));
+ ret = EFAULT;
+ goto done;
+ }
+
+ *out = ctx;
+ ret = EOK;
+
+done:
+ if (ret != EOK) {
+ talloc_free(ctx);
+ }
+ return ret;
+}
+
+int sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb,
+ const char *domain, struct sss_names_ctx **out)
+{
+ TALLOC_CTX *tmpctx = NULL;
+ char *conf_path;
+ char *re_pattern;
+ char *fq_fmt;
+ int ret;
+
tmpctx = talloc_new(NULL);
if (tmpctx == NULL) {
ret = ENOMEM;
@@ -162,19 +203,19 @@ int sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb,
goto done;
}
- ret = confdb_get_string(cdb, ctx, conf_path,
- CONFDB_NAME_REGEX, NULL, &ctx->re_pattern);
+ ret = confdb_get_string(cdb, tmpctx, conf_path,
+ CONFDB_NAME_REGEX, NULL, &re_pattern);
if (ret != EOK) goto done;
/* If not found in the domain, look in globals */
- if (ctx->re_pattern == NULL) {
- ret = confdb_get_string(cdb, ctx, CONFDB_MONITOR_CONF_ENTRY,
- CONFDB_NAME_REGEX, NULL, &ctx->re_pattern);
+ if (re_pattern == NULL) {
+ ret = confdb_get_string(cdb, tmpctx, CONFDB_MONITOR_CONF_ENTRY,
+ CONFDB_NAME_REGEX, NULL, &re_pattern);
if (ret != EOK) goto done;
}
- if (ctx->re_pattern == NULL) {
- ret = get_id_provider_default_re(ctx, cdb, conf_path, &ctx->re_pattern);
+ if (re_pattern == NULL) {
+ ret = get_id_provider_default_re(tmpctx, cdb, conf_path, &re_pattern);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("Failed to get provider default regular " \
"expression for domain [%s].\n", domain));
@@ -182,10 +223,10 @@ int sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb,
}
}
- if (!ctx->re_pattern) {
- ctx->re_pattern = talloc_strdup(ctx,
- "(?P<name>[^@]+)@?(?P<domain>[^@]*$)");
- if (!ctx->re_pattern) {
+ if (!re_pattern) {
+ re_pattern = talloc_strdup(tmpctx,
+ "(?P<name>[^@]+)@?(?P<domain>[^@]*$)");
+ if (!re_pattern) {
ret = ENOMEM;
goto done;
}
@@ -195,49 +236,33 @@ int sss_names_init(TALLOC_CTX *mem_ctx, struct confdb_ctx *cdb,
"not support non-unique named subpatterns.\n"));
DEBUG(2, ("Please make sure that your pattern [%s] only contains "
"subpatterns with a unique name and uses "
- "the Python syntax (?P<name>).\n", ctx->re_pattern));
+ "the Python syntax (?P<name>).\n", re_pattern));
#endif
}
- DEBUG(SSSDBG_CONF_SETTINGS, ("Using re [%s].\n", ctx->re_pattern));
-
- ret = confdb_get_string(cdb, ctx, conf_path,
- CONFDB_FULL_NAME_FORMAT, NULL, &ctx->fq_fmt);
+ ret = confdb_get_string(cdb, tmpctx, conf_path,
+ CONFDB_FULL_NAME_FORMAT, NULL, &fq_fmt);
if (ret != EOK) goto done;
/* If not found in the domain, look in globals */
- if (ctx->fq_fmt == NULL) {
- ret = confdb_get_string(cdb, ctx, CONFDB_MONITOR_CONF_ENTRY,
- CONFDB_FULL_NAME_FORMAT, NULL, &ctx->fq_fmt);
+ if (fq_fmt == NULL) {
+ ret = confdb_get_string(cdb, tmpctx, CONFDB_MONITOR_CONF_ENTRY,
+ CONFDB_FULL_NAME_FORMAT, NULL, &fq_fmt);
if (ret != EOK) goto done;
}
- if (!ctx->fq_fmt) {
- ctx->fq_fmt = talloc_strdup(ctx, "%1$s@%2$s");
- if (!ctx->fq_fmt) {
+ if (!fq_fmt) {
+ fq_fmt = talloc_strdup(tmpctx, "%1$s@%2$s");
+ if (!fq_fmt) {
ret = ENOMEM;
goto done;
}
}
- ctx->re = pcre_compile2(ctx->re_pattern,
- NAME_DOMAIN_PATTERN_OPTIONS,
- &errval, &errstr, &errpos, NULL);
- if (!ctx->re) {
- DEBUG(1, ("Invalid Regular Expression pattern at position %d."
- " (Error: %d [%s])\n", errpos, errval, errstr));
- ret = EFAULT;
- goto done;
- }
-
- *out = ctx;
- ret = EOK;
+ ret = sss_names_init_from_args(mem_ctx, re_pattern, fq_fmt, out);
done:
talloc_free(tmpctx);
- if (ret != EOK) {
- talloc_free(ctx);
- }
return ret;
}
diff --git a/src/util/util.h b/src/util/util.h
index 33725f63591a4d165a084c1fd361f9651e80e50b..49dc850c36cedd83755034367357fab41bd32ec6 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -401,6 +401,13 @@ struct sss_names_ctx {
pcre *re;
};
+/* initialize sss_names_ctx directly from arguments */
+int sss_names_init_from_args(TALLOC_CTX *mem_ctx,
+ const char *re_pattern,
+ const char *fq_fmt,
+ struct sss_names_ctx **out);
+
+/* initialize sss_names_ctx from domain configuration */
int sss_names_init(TALLOC_CTX *mem_ctx,
struct confdb_ctx *cdb,
const char *domain,
--
1.8.2.1

View File

@ -0,0 +1,116 @@
From 728b10c81204929be5669c1e67bd086e09c47c00 Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jcholast@redhat.com>
Date: Fri, 26 Apr 2013 09:53:47 +0200
Subject: [PATCH 4/6] SSH: Fix parsing of names from client requests
Try to parse names in the form user@domain first, as that's what sss_ssh_*
send in requests when the --domain option is used. Do not parse host names
using domain-specific regular expression.
---
src/responder/ssh/sshsrv.c | 8 ++++++++
src/responder/ssh/sshsrv_cmd.c | 23 ++++++++++++++++++++---
src/responder/ssh/sshsrv_private.h | 2 ++
3 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/src/responder/ssh/sshsrv.c b/src/responder/ssh/sshsrv.c
index 8a66f2239ac370218ec48d4cfc003d40dc1b7aec..410e631af43b8e8ef160334bab9a540ea913804c 100644
--- a/src/responder/ssh/sshsrv.c
+++ b/src/responder/ssh/sshsrv.c
@@ -118,6 +118,14 @@ int ssh_process_init(TALLOC_CTX *mem_ctx,
ssh_ctx->rctx = rctx;
ssh_ctx->rctx->pvt_ctx = ssh_ctx;
+ ret = sss_names_init_from_args(ssh_ctx,
+ "(?P<name>[^@]+)@?(?P<domain>[^@]*$)",
+ "%1$s@%2$s", &ssh_ctx->snctx);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_FATAL_FAILURE, ("fatal error initializing regex data\n"));
+ goto fail;
+ }
+
/* Enable automatic reconnection to the Data Provider */
ret = confdb_get_int(ssh_ctx->rctx->cdb,
CONFDB_SSH_CONF_ENTRY,
diff --git a/src/responder/ssh/sshsrv_cmd.c b/src/responder/ssh/sshsrv_cmd.c
index 671160ea77904bc5d9a74fee1e351fec8b7cb3fb..374abe6c6ef4ffe1abeeafa2fe94602f5bff3414 100644
--- a/src/responder/ssh/sshsrv_cmd.c
+++ b/src/responder/ssh/sshsrv_cmd.c
@@ -55,6 +55,7 @@ sss_ssh_cmd_get_user_pubkeys(struct cli_ctx *cctx)
return ENOMEM;
}
cmd_ctx->cctx = cctx;
+ cmd_ctx->is_user = true;
ret = ssh_cmd_parse_request(cmd_ctx);
if (ret != EOK) {
@@ -101,6 +102,7 @@ sss_ssh_cmd_get_host_pubkeys(struct cli_ctx *cctx)
return ENOMEM;
}
cmd_ctx->cctx = cctx;
+ cmd_ctx->is_user = false;
ret = ssh_cmd_parse_request(cmd_ctx);
if (ret != EOK) {
@@ -673,6 +675,8 @@ static errno_t
ssh_cmd_parse_request(struct ssh_cmd_ctx *cmd_ctx)
{
struct cli_ctx *cctx = cmd_ctx->cctx;
+ struct ssh_ctx *ssh_ctx = talloc_get_type(cctx->rctx->pvt_ctx,
+ struct ssh_ctx);
errno_t ret;
uint8_t *body;
size_t body_len;
@@ -705,14 +709,27 @@ ssh_cmd_parse_request(struct ssh_cmd_ctx *cmd_ctx)
}
c += name_len;
- ret = sss_parse_name_for_domains(cmd_ctx, cctx->rctx->domains,
- cctx->rctx->default_domain,name,
- &cmd_ctx->domname, &cmd_ctx->name);
+ ret = sss_parse_name(cmd_ctx, ssh_ctx->snctx, name,
+ &cmd_ctx->domname, &cmd_ctx->name);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("Invalid name received [%s]\n", name));
return ENOENT;
}
+ if (cmd_ctx->is_user && cmd_ctx->domname == NULL) {
+ name = cmd_ctx->name;
+
+ ret = sss_parse_name_for_domains(cmd_ctx, cctx->rctx->domains,
+ cctx->rctx->default_domain, name,
+ &cmd_ctx->domname,
+ &cmd_ctx->name);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Invalid name received [%s]\n", name));
+ return ENOENT;
+ }
+ }
+
if (flags & 1) {
SAFEALIGN_COPY_UINT32_CHECK(&alias_len, body+c, body_len, &c);
if (alias_len == 0 || alias_len > body_len - c) {
diff --git a/src/responder/ssh/sshsrv_private.h b/src/responder/ssh/sshsrv_private.h
index 296bd94a2947796198a0559c06d904b389283ade..ebb30ce7cbc982bb29b73592d5873e7d3652228a 100644
--- a/src/responder/ssh/sshsrv_private.h
+++ b/src/responder/ssh/sshsrv_private.h
@@ -28,6 +28,7 @@
struct ssh_ctx {
struct resp_ctx *rctx;
+ struct sss_names_ctx *snctx;
bool hash_known_hosts;
int known_hosts_timeout;
@@ -38,6 +39,7 @@ struct ssh_cmd_ctx {
char *name;
char *alias;
char *domname;
+ bool is_user;
struct sss_domain_info *domain;
bool check_next;
--
1.8.2.1

View File

@ -0,0 +1,315 @@
From 28e55560008f21a532b103b3f612c6fca2a54d76 Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jcholast@redhat.com>
Date: Fri, 26 Apr 2013 10:45:42 +0200
Subject: [PATCH 5/6] SSH: Use separate field for domain name in client
requests
Instead of appending @domain to names when the --domain option of sss_ssh_* is
used, put domain name in a separate field in client requests.
---
src/responder/ssh/sshsrv_cmd.c | 91 +++++++++++++++++++---------
src/sss_client/ssh/sss_ssh_authorizedkeys.c | 15 +----
src/sss_client/ssh/sss_ssh_client.c | 38 ++++++++----
src/sss_client/ssh/sss_ssh_client.h | 1 +
src/sss_client/ssh/sss_ssh_knownhostsproxy.c | 12 +---
src/util/sss_ssh.h | 4 ++
6 files changed, 97 insertions(+), 64 deletions(-)
diff --git a/src/responder/ssh/sshsrv_cmd.c b/src/responder/ssh/sshsrv_cmd.c
index 374abe6c6ef4ffe1abeeafa2fe94602f5bff3414..d2f889fa6ac1e414dfa9bbd943b8ef6af125ae74 100644
--- a/src/responder/ssh/sshsrv_cmd.c
+++ b/src/responder/ssh/sshsrv_cmd.c
@@ -685,12 +685,14 @@ ssh_cmd_parse_request(struct ssh_cmd_ctx *cmd_ctx)
uint32_t name_len;
char *name;
uint32_t alias_len;
- char *alias;
+ char *alias = NULL;
+ uint32_t domain_len;
+ char *domain = cctx->rctx->default_domain;
sss_packet_get_body(cctx->creq->in, &body, &body_len);
SAFEALIGN_COPY_UINT32_CHECK(&flags, body+c, body_len, &c);
- if (flags > 1) {
+ if (flags & ~(uint32_t)SSS_SSH_REQ_MASK) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid flags received [0x%x]\n", flags));
return EINVAL;
}
@@ -709,28 +711,7 @@ ssh_cmd_parse_request(struct ssh_cmd_ctx *cmd_ctx)
}
c += name_len;
- ret = sss_parse_name(cmd_ctx, ssh_ctx->snctx, name,
- &cmd_ctx->domname, &cmd_ctx->name);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE, ("Invalid name received [%s]\n", name));
- return ENOENT;
- }
-
- if (cmd_ctx->is_user && cmd_ctx->domname == NULL) {
- name = cmd_ctx->name;
-
- ret = sss_parse_name_for_domains(cmd_ctx, cctx->rctx->domains,
- cctx->rctx->default_domain, name,
- &cmd_ctx->domname,
- &cmd_ctx->name);
- if (ret != EOK) {
- DEBUG(SSSDBG_OP_FAILURE,
- ("Invalid name received [%s]\n", name));
- return ENOENT;
- }
- }
-
- if (flags & 1) {
+ if (flags & SSS_SSH_REQ_ALIAS) {
SAFEALIGN_COPY_UINT32_CHECK(&alias_len, body+c, body_len, &c);
if (alias_len == 0 || alias_len > body_len - c) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid alias length\n"));
@@ -744,11 +725,67 @@ ssh_cmd_parse_request(struct ssh_cmd_ctx *cmd_ctx)
return EINVAL;
}
c += alias_len;
+ }
- if (strcmp(cmd_ctx->name, alias) != 0) {
- cmd_ctx->alias = talloc_strdup(cmd_ctx, alias);
- if (!cmd_ctx->alias) return ENOMEM;
+ if (flags & SSS_SSH_REQ_DOMAIN) {
+ SAFEALIGN_COPY_UINT32_CHECK(&domain_len, body+c, body_len, &c);
+ if (domain_len > 0) {
+ if (domain_len > body_len - c) {
+ DEBUG(SSSDBG_CRIT_FAILURE, ("Invalid domain length\n"));
+ return EINVAL;
+ }
+
+ domain = (char *)(body+c);
+ if (!sss_utf8_check((const uint8_t *)domain, domain_len-1) ||
+ domain[domain_len-1] != 0) {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ ("Domain is not valid UTF-8 string\n"));
+ return EINVAL;
+ }
+ c += domain_len;
+ }
+
+ DEBUG(SSSDBG_TRACE_FUNC,
+ ("Requested domain [%s]\n", domain ? domain : "<ALL>"));
+ } else {
+ DEBUG(SSSDBG_TRACE_FUNC, ("Splitting domain from name [%s]\n", name));
+
+ ret = sss_parse_name(cmd_ctx, ssh_ctx->snctx, name,
+ &cmd_ctx->domname, &cmd_ctx->name);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Invalid name received [%s]\n", name));
+ return ENOENT;
}
+
+ name = cmd_ctx->name;
+ }
+
+ if (cmd_ctx->is_user && cmd_ctx->domname == NULL) {
+ DEBUG(SSSDBG_TRACE_FUNC,
+ ("Parsing name [%s][%s]\n", name, domain ? domain : "<ALL>"));
+
+ ret = sss_parse_name_for_domains(cmd_ctx, cctx->rctx->domains,
+ domain, name,
+ &cmd_ctx->domname,
+ &cmd_ctx->name);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ ("Invalid name received [%s]\n", name));
+ return ENOENT;
+ }
+ } else if (cmd_ctx->name == NULL && cmd_ctx->domname == NULL) {
+ cmd_ctx->name = talloc_strdup(cmd_ctx, name);
+ if (!cmd_ctx->name) return ENOMEM;
+
+ if (domain != NULL) {
+ cmd_ctx->domname = talloc_strdup(cmd_ctx, domain);
+ if (!cmd_ctx->domname) return ENOMEM;
+ }
+ }
+
+ if (alias != NULL && strcmp(cmd_ctx->name, alias) != 0) {
+ cmd_ctx->alias = talloc_strdup(cmd_ctx, alias);
+ if (!cmd_ctx->alias) return ENOMEM;
}
return EOK;
diff --git a/src/sss_client/ssh/sss_ssh_authorizedkeys.c b/src/sss_client/ssh/sss_ssh_authorizedkeys.c
index 11deff9a6bb2592ce102ff314bcb2b92f90fa1da..bc991a837635186449b1fd5f1c6bdc944176c43d 100644
--- a/src/sss_client/ssh/sss_ssh_authorizedkeys.c
+++ b/src/sss_client/ssh/sss_ssh_authorizedkeys.c
@@ -43,7 +43,6 @@ int main(int argc, const char **argv)
POPT_TABLEEND
};
poptContext pc = NULL;
- const char *user;
struct sss_ssh_ent *ent;
size_t i;
char *repr;
@@ -84,21 +83,9 @@ int main(int argc, const char **argv)
BAD_POPT_PARAMS(pc, _("User not specified\n"), ret, fini);
}
- /* append domain to username if domain is specified */
- if (pc_domain) {
- user = talloc_asprintf(mem_ctx, "%s@%s", pc_user, pc_domain);
- if (!user) {
- ERROR("Not enough memory\n");
- ret = EXIT_FAILURE;
- goto fini;
- }
- } else {
- user = pc_user;
- }
-
/* look up public keys */
ret = sss_ssh_get_ent(mem_ctx, SSS_SSH_GET_USER_PUBKEYS,
- user, NULL, &ent);
+ pc_user, pc_domain, NULL, &ent);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
("sss_ssh_get_ent() failed (%d): %s\n", ret, strerror(ret)));
diff --git a/src/sss_client/ssh/sss_ssh_client.c b/src/sss_client/ssh/sss_ssh_client.c
index 645f2928985637f26213ab7a0d48a626b088ad58..5312dba2be32aa0cc8813dedfc4189edeff7085c 100644
--- a/src/sss_client/ssh/sss_ssh_client.c
+++ b/src/sss_client/ssh/sss_ssh_client.c
@@ -70,29 +70,34 @@ int set_locale(void)
/* SSH public key request:
*
- * 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)
- * }
+ * header:
+ * 0..3: flags (unsigned int, must be combination of SSS_SSH_REQ_* flags)
+ * 4..7: name length (unsigned int)
+ * 8..X: name (null-terminated UTF-8 string)
+ * alias (only included if flags & SSS_SSH_REQ_ALIAS):
+ * 0..3: alias length (unsigned int)
+ * 4..X: alias (null-terminated UTF-8 string)
+ * domain (ony included if flags & SSS_SSH_REQ_DOMAIN):
+ * 0..3: domain length (unsigned int, 0 means default domain)
+ * 4..X: domain (null-terminated UTF-8 string)
*
* SSH public key reply:
*
- * 0..3: number of results (unsigned int)
- * 4..7: reserved (unsigned int, must be 0)
- * 8..$: array of results:
+ * header:
+ * 0..3: number of results (unsigned int)
+ * 4..7: reserved (unsigned int, must be 0)
+ * results (repeated for each result):
* 0..3: flags (unsigned int, must be 0)
* 4..7: name length (unsigned int)
* 8..(X-1): name (null-terminated UTF-8 string)
* X..(X+3): key length (unsigned int)
- * (X+4)..Y: key (public key blob as defined in RFC4253, section 6.6)
+ * (X+4)..Y: key (public key data)
*/
errno_t
sss_ssh_get_ent(TALLOC_CTX *mem_ctx,
enum sss_cli_command command,
const char *name,
+ const char *domain,
const char *alias,
struct sss_ssh_ent **result)
{
@@ -102,6 +107,7 @@ sss_ssh_get_ent(TALLOC_CTX *mem_ctx,
uint32_t flags;
uint32_t name_len;
uint32_t alias_len;
+ uint32_t domain_len;
size_t req_len;
uint8_t *req = NULL;
size_t c = 0;
@@ -122,11 +128,15 @@ sss_ssh_get_ent(TALLOC_CTX *mem_ctx,
req_len = 2*sizeof(uint32_t) + name_len;
if (alias) {
- flags |= 1;
+ flags |= SSS_SSH_REQ_ALIAS;
alias_len = strlen(alias)+1;
req_len += sizeof(uint32_t) + alias_len;
}
+ flags |= SSS_SSH_REQ_DOMAIN;
+ domain_len = domain ? (strlen(domain)+1) : 0;
+ req_len += sizeof(uint32_t) + domain_len;
+
req = talloc_array(tmp_ctx, uint8_t, req_len);
if (!req) {
ret = ENOMEM;
@@ -140,6 +150,10 @@ sss_ssh_get_ent(TALLOC_CTX *mem_ctx,
SAFEALIGN_SET_UINT32(req+c, alias_len, &c);
safealign_memcpy(req+c, alias, alias_len, &c);
}
+ SAFEALIGN_SET_UINT32(req+c, domain_len, &c);
+ if (domain_len > 0) {
+ safealign_memcpy(req+c, domain, domain_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 7ffc3983e11c4cfb5fcef9ff417592f63fef3b74..5ad0643f9b821d1ceec85c477ee2037c73e73d7f 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 *domain,
const char *alias,
struct sss_ssh_ent **result);
diff --git a/src/sss_client/ssh/sss_ssh_knownhostsproxy.c b/src/sss_client/ssh/sss_ssh_knownhostsproxy.c
index 600895d1fec81be59f0a6e0092b8a6c9f17890ec..e2202b1839214a165d5a94e3c70ce6af47cb9187 100644
--- a/src/sss_client/ssh/sss_ssh_knownhostsproxy.c
+++ b/src/sss_client/ssh/sss_ssh_knownhostsproxy.c
@@ -282,19 +282,9 @@ int main(int argc, const char **argv)
}
if (host) {
- /* append domain to hostname if domain is specified */
- if (pc_domain) {
- host = talloc_asprintf(mem_ctx, "%s@%s", host, pc_domain);
- if (!host) {
- DEBUG(SSSDBG_CRIT_FAILURE, ("Not enough memory\n"));
- ret = EXIT_FAILURE;
- goto fini;
- }
- }
-
/* look up public keys */
ret = sss_ssh_get_ent(mem_ctx, SSS_SSH_GET_HOST_PUBKEYS,
- host, pc_host, &ent);
+ host, pc_domain, pc_host, &ent);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
("sss_ssh_get_ent() failed (%d): %s\n", ret, strerror(ret)));
diff --git a/src/util/sss_ssh.h b/src/util/sss_ssh.h
index fec7c732bdb319a906e01ec185d7ff0e7f2de0fe..1ba50a6552904096f8950b1f53563d7903eaf786 100644
--- a/src/util/sss_ssh.h
+++ b/src/util/sss_ssh.h
@@ -21,6 +21,10 @@
#ifndef _SSS_SSH_H_
#define _SSS_SSH_H_
+#define SSS_SSH_REQ_ALIAS 0x01
+#define SSS_SSH_REQ_DOMAIN 0x02
+#define SSS_SSH_REQ_MASK 0x03
+
struct sss_ssh_pubkey {
uint8_t *data;
size_t data_len;
--
1.8.2.1

View File

@ -0,0 +1,30 @@
From d5fcc4c497eb17404812be7600fb1181a75cbfd3 Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jcholast@redhat.com>
Date: Fri, 26 Apr 2013 10:07:22 +0200
Subject: [PATCH 6/6] SSH: Do not skip domains with use_fully_qualified_names
in host key requests
---
src/responder/ssh/sshsrv_cmd.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/src/responder/ssh/sshsrv_cmd.c b/src/responder/ssh/sshsrv_cmd.c
index d2f889fa6ac1e414dfa9bbd943b8ef6af125ae74..bb765c62890aa326cfad87f511622167df61f0a1 100644
--- a/src/responder/ssh/sshsrv_cmd.c
+++ b/src/responder/ssh/sshsrv_cmd.c
@@ -300,12 +300,6 @@ ssh_host_pubkeys_search(struct ssh_cmd_ctx *cmd_ctx)
struct tevent_req *req;
struct dp_callback_ctx *cb_ctx;
- /* if it is a domainless search, skip domains that require fully
- * qualified names instead */
- while (cmd_ctx->domain && cmd_ctx->check_next && cmd_ctx->domain->fqnames) {
- cmd_ctx->domain = get_next_domain(cmd_ctx->domain, false);
- }
-
if (!cmd_ctx->domain) {
DEBUG(SSSDBG_OP_FAILURE,
("No matching domain found for [%s], fail!\n", cmd_ctx->name));
--
1.8.2.1

View File

@ -16,7 +16,7 @@
Name: sssd
Version: 1.10.0
Release: 3%{?dist}.beta1
Release: 4%{?dist}.beta1
Group: Applications/System
Summary: System Security Services Daemon
License: GPLv3+
@ -25,6 +25,13 @@ Source0: https://fedorahosted.org/released/sssd/%{name}-%{version}beta1.tar.gz
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
### Patches ###
Patch0001: 0001-AD-read-flat-name-and-SID-of-the-AD-domain.patch
Patch0002: 0002-Actually-use-the-index-parameter-in-resolv_get_socka.patch
Patch0003: 0003-UTIL-Add-function-sss_names_init_from_args.patch
Patch0004: 0004-SSH-Fix-parsing-of-names-from-client-requests.patch
Patch0005: 0005-SSH-Use-separate-field-for-domain-name-in-client-req.patch
Patch0006: 0006-SSH-Do-not-skip-domains-with-use_fully_qualified_nam.patch
Patch0501: 0501-FEDORA-Switch-the-default-ccache-location.patch
### Dependencies ###
@ -38,6 +45,7 @@ Requires: libipa_hbac%{?_isa} = %{version}-%{release}
Requires: libsss_idmap%{?_isa} = %{version}-%{release}
Requires: python-sssdconfig = %{version}-%{release}
Requires: krb5-libs%{?_isa} >= 1.10
Requires: libini_config >= 1.0.0.1
Requires(post): systemd-units initscripts chkconfig
Requires(preun): systemd-units initscripts chkconfig
Requires(postun): systemd-units initscripts chkconfig
@ -595,6 +603,12 @@ fi
%postun -n libsss_sudo -p /sbin/ldconfig
%changelog
* Tue May 7 2013 Jakub Hrozek <jhrozek@redhat.com> - 1.10.0-4.beta1
- Explicitly Require libini_config >= 1.0.0.1 to work around a SONAME bug
in ding-libs
- Fix SSH integration with fully-qualified domains
- Add the ability to dynamically discover the NetBIOS name
* Fri May 3 2013 Jakub Hrozek <jhrozek@redhat.com> - 1.10.0-3.beta1
- New upstream release 1.10 beta1
- https://fedorahosted.org/sssd/wiki/Releases/Notes-1.10.0beta1