summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/providers/ad/ad_id.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
index 20f9c23fa..87b69c668 100644
--- a/src/providers/ad/ad_id.c
+++ b/src/providers/ad/ad_id.c
@@ -20,10 +20,12 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "util/util.h"
+#include "util/strtonum.h"
#include "providers/ad/ad_common.h"
#include "providers/ad/ad_id.h"
#include "providers/ad/ad_domain_info.h"
#include "providers/ldap/sdap_async_enum.h"
+#include "providers/ldap/sdap_idmap.h"
struct ad_handle_acct_info_state {
struct be_req *breq;
@@ -222,6 +224,84 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx,
return clist;
}
+static errno_t ad_account_can_shortcut(struct be_ctx *be_ctx,
+ struct sdap_idmap_ctx *idmap_ctx,
+ int filter_type,
+ const char *filter_value,
+ const char *filter_domain,
+ bool *_shortcut)
+{
+ struct sss_domain_info *domain = be_ctx->domain;
+ struct sss_domain_info *req_dom = NULL;
+ enum idmap_error_code err;
+ char *sid = NULL;
+ const char *csid = NULL;
+ uint32_t id;
+ bool shortcut = false;
+ errno_t ret;
+
+ if (!sdap_idmap_domain_has_algorithmic_mapping(idmap_ctx, domain->name,
+ domain->domain_id)) {
+ shortcut = false;
+ ret = EOK;
+ goto done;
+ }
+
+ switch (filter_type) {
+ case BE_FILTER_IDNUM:
+ /* convert value to ID */
+ errno = 0;
+ id = strtouint32(filter_value, NULL, 10);
+ if (errno != 0) {
+ ret = errno;
+ goto done;
+ }
+
+ /* convert the ID to its SID equivalent */
+ err = sss_idmap_unix_to_sid(idmap_ctx->map, id, &sid);
+ if (err != IDMAP_SUCCESS) {
+ DEBUG(SSSDBG_MINOR_FAILURE, ("Mapping ID [%s] to SID failed: "
+ "[%s]\n", filter_value, idmap_error_string(err)));
+ ret = EIO;
+ goto done;
+ }
+ /* fall through */
+ case BE_FILTER_SECID:
+ csid = sid == NULL ? filter_value : sid;
+
+ req_dom = find_subdomain_by_sid(domain, csid);
+ if (req_dom == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, ("Invalid domain\n"));
+ ret = ERR_DOMAIN_NOT_FOUND;
+ goto done;
+ }
+
+ if (strcasecmp(req_dom->name, filter_domain) != 0) {
+ shortcut = true;
+ } else {
+ shortcut = false;
+ }
+ break;
+ default:
+ shortcut = false;
+ break;
+ }
+
+ ret = EOK;
+
+done:
+ if (sid != NULL) {
+ /* FIXME: use library function when #2133 is fixed */
+ talloc_free(sid);
+ }
+
+ if (ret == EOK) {
+ *_shortcut = shortcut;
+ }
+
+ return ret;
+}
+
static void ad_account_info_complete(struct tevent_req *req);
void
@@ -235,6 +315,7 @@ ad_account_info_handler(struct be_req *be_req)
struct sss_domain_info *dom;
struct sdap_domain *sdom;
struct sdap_id_conn_ctx **clist;
+ bool shortcut;
errno_t ret;
ad_ctx = talloc_get_type(be_ctx->bet_info[BET_ID].pvt_bet_data,
@@ -246,6 +327,21 @@ ad_account_info_handler(struct be_req *be_req)
return be_req_terminate(be_req, DP_ERR_OFFLINE, EAGAIN, "Offline");
}
+ /* Try to shortcut if this is ID or SID search and it belongs to
+ * other domain range than is in ar->domain. */
+ ret = ad_account_can_shortcut(be_ctx, sdap_id_ctx->opts->idmap_ctx,
+ ar->filter_type, ar->filter_value,
+ ar->domain, &shortcut);
+ if (ret != EOK) {
+ goto fail;
+ }
+
+ if (shortcut) {
+ DEBUG(SSSDBG_TRACE_FUNC, ("This ID is from different domain\n"));
+ be_req_terminate(be_req, DP_ERR_OK, EOK, NULL);
+ return;
+ }
+
dom = be_ctx->domain;
if (strcasecmp(ar->domain, be_ctx->domain->name) != 0) {
/* Subdomain request, verify subdomain */