URL: https://github.com/SSSD/sssd/pull/966
Author: sumit-bose
 Title: #966: ad: add ad_use_ldaps
Action: opened

PR body:
"""
With this new boolean option the AD provider should only use the LDAPS port
636 and the Global Catalog port 3629 which is TLS protected as well.

Related to https://pagure.io/SSSD/sssd/issue/4131
"""

To pull the PR as Git branch:
git remote add ghsssd https://github.com/SSSD/sssd
git fetch ghsssd pull/966/head:pr966
git checkout pr966
From 3dadb248440f2e7a02c68049001f848459dd1bdf Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Thu, 26 Sep 2019 20:24:34 +0200
Subject: [PATCH 1/4] ad: allow booleans for ad_inherit_opts_if_needed()

Currently ad_inherit_opts_if_needed() can only handle strings. With this
patch it can handle boolean options as well.

Related to https://pagure.io/SSSD/sssd/issue/4131
---
 src/providers/ad/ad_common.c | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
index 5540066d4e..600e3ceb2c 100644
--- a/src/providers/ad/ad_common.c
+++ b/src/providers/ad/ad_common.c
@@ -1479,9 +1479,26 @@ errno_t ad_inherit_opts_if_needed(struct dp_option *parent_opts,
     const char *parent_val = NULL;
     char *dummy = NULL;
     char *option_list[2] = { NULL, NULL };
-
-    parent_val = dp_opt_get_cstring(parent_opts, opt_id);
-    if (parent_val != NULL) {
+    bool is_default = true;
+
+    switch (parent_opts[opt_id].type) {
+    case DP_OPT_STRING:
+        parent_val = dp_opt_get_cstring(parent_opts, opt_id);
+        break;
+    case DP_OPT_BOOL:
+        /* For booleans it is hard to say if the option is set or not since
+         * both possible values are valid ones. So we check if the value is
+         * different from the default and skip if it is the default. In this
+         * case the sub-domain option would either be the default as well or
+         * manully set and in both cases we do not have to change it. */
+        is_default = (parent_opts[opt_id].val.boolean
+                                == parent_opts[opt_id].def_val.boolean);
+        break;
+    default:
+        DEBUG(SSSDBG_TRACE_FUNC, "Unsupported type, skipping.\n");
+    }
+
+    if (parent_val != NULL || !is_default) {
         ret = confdb_get_string(cdb, NULL, subdom_conf_path,
                                 parent_opts[opt_id].opt_name, NULL, &dummy);
         if (ret != EOK) {

From 33c8757087b8649926e53cf494e2a775ad100302 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Thu, 26 Sep 2019 20:27:09 +0200
Subject: [PATCH 2/4] ad: add ad_use_ldaps

With this new boolean option the AD provider should only use the LDAPS
port 636 and the Global Catalog port 3629 which is TLS protected as
well.

Related to https://pagure.io/SSSD/sssd/issue/4131
---
 src/config/SSSDConfig/__init__.py.in      |  1 +
 src/config/cfg_rules.ini                  |  1 +
 src/config/etc/sssd.api.d/sssd-ad.conf    |  1 +
 src/man/sssd-ad.5.xml                     | 20 +++++++++++++++++++
 src/providers/ad/ad_common.c              | 24 +++++++++++++++++++----
 src/providers/ad/ad_common.h              |  8 +++++++-
 src/providers/ad/ad_init.c                |  8 +++++++-
 src/providers/ad/ad_opts.c                |  1 +
 src/providers/ad/ad_srv.c                 | 16 ++++++++++++---
 src/providers/ad/ad_srv.h                 |  3 ++-
 src/providers/ad/ad_subdomains.c          | 21 ++++++++++++++++++--
 src/providers/ipa/ipa_subdomains_server.c |  4 ++--
 12 files changed, 94 insertions(+), 14 deletions(-)

diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
index 92e6141170..6c2a1ce441 100644
--- a/src/config/SSSDConfig/__init__.py.in
+++ b/src/config/SSSDConfig/__init__.py.in
@@ -253,6 +253,7 @@ option_strings = {
     'ad_maximum_machine_account_password_age' : _('Maximum age in days before the machine account password should be renewed'),
     'ad_machine_account_password_renewal_opts' : _('Option for tuning the machine account renewal task'),
     'ad_update_samba_machine_account_password' : _('Whether to update the machine account password in the Samba database'),
+    'ad_use_ldaps' : _('Use LDAPS port for LDAP and Global Catalog requests'),
 
     # [provider/krb5]
     'krb5_kdcip' : _('Kerberos server address'),
diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini
index f7c1d4ce2c..478ca9eb43 100644
--- a/src/config/cfg_rules.ini
+++ b/src/config/cfg_rules.ini
@@ -465,6 +465,7 @@ option = ad_maximum_machine_account_password_age
 option = ad_server
 option = ad_site
 option = ad_update_samba_machine_account_password
+option = ad_use_ldaps
 
 # IPA provider specific options
 option = ipa_anchor_uuid
diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf
index 33f040c8e6..51cdad536e 100644
--- a/src/config/etc/sssd.api.d/sssd-ad.conf
+++ b/src/config/etc/sssd.api.d/sssd-ad.conf
@@ -21,6 +21,7 @@ ad_site = str, None, false
 ad_maximum_machine_account_password_age = int, None, false
 ad_machine_account_password_renewal_opts = str, None, false
 ad_update_samba_machine_account_password = bool, None, false
+ad_use_ldaps = bool, None, false
 ldap_uri = str, None, false
 ldap_backup_uri = str, None, false
 ldap_search_base = str, None, false
diff --git a/src/man/sssd-ad.5.xml b/src/man/sssd-ad.5.xml
index 30c7d07cfa..a634d4f41c 100644
--- a/src/man/sssd-ad.5.xml
+++ b/src/man/sssd-ad.5.xml
@@ -1031,6 +1031,26 @@ ad_gpo_map_deny = +my_pam_service
                     </listitem>
                 </varlistentry>
 
+                <varlistentry>
+                    <term>ad_use_ldaps (bool)</term>
+                    <listitem>
+                        <para>
+                            By default SSSD uses the plain LDAP port 389 and the
+                            Global Catalog port 3628. If this option is set to
+                            True SSSD will use the LDAPS port 636 and Global
+                            Catalog port 3629 with LDAPS protection. Since AD
+                            does not allow to have multiple encryption layers on
+                            a single connection and we still want to use
+                            SASL/GSSAPI or SASL/GSS-SPNEGO for authentication
+                            the SASL security property maxssf is set to 0 (zero)
+                            for those connections.
+                        </para>
+                        <para>
+                            Default: False
+                        </para>
+                    </listitem>
+                </varlistentry>
+
                 <varlistentry>
                     <term>dyndns_update (boolean)</term>
                     <listitem>
diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
index 600e3ceb2c..a2369166a2 100644
--- a/src/providers/ad/ad_common.c
+++ b/src/providers/ad/ad_common.c
@@ -729,6 +729,7 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
                  const char *ad_gc_service,
                  const char *ad_domain,
                  bool use_kdcinfo,
+                 bool ad_use_ldaps,
                  size_t n_lookahead_primary,
                  size_t n_lookahead_backup,
                  struct ad_service **_service)
@@ -746,6 +747,16 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *bectx,
         goto done;
     }
 
+    if (ad_use_ldaps) {
+        service->ldap_scheme = "ldaps";
+        service->port = LDAPS_PORT;
+        service->gc_port = AD_GC_LDAPS_PORT;
+    } else {
+        service->ldap_scheme = "ldap";
+        service->port = LDAP_PORT;
+        service->gc_port = AD_GC_PORT;
+    }
+
     service->sdap = talloc_zero(service, struct sdap_service);
     service->gc = talloc_zero(service, struct sdap_service);
     if (!service->sdap || !service->gc) {
@@ -927,7 +938,8 @@ ad_resolve_callback(void *private_data, struct fo_server *server)
         goto done;
     }
 
-    new_uri = talloc_asprintf(service->sdap, "ldap://%s";, srv_name);
+    new_uri = talloc_asprintf(service->sdap, "%s://%s", service->ldap_scheme,
+                                                        srv_name);
     if (!new_uri) {
         DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy URI\n");
         ret = ENOMEM;
@@ -935,7 +947,7 @@ ad_resolve_callback(void *private_data, struct fo_server *server)
     }
     DEBUG(SSSDBG_CONF_SETTINGS, "Constructed uri '%s'\n", new_uri);
 
-    sockaddr = resolv_get_sockaddr_address(tmp_ctx, srvaddr, LDAP_PORT);
+    sockaddr = resolv_get_sockaddr_address(tmp_ctx, srvaddr, service->port);
     if (sockaddr == NULL) {
         DEBUG(SSSDBG_CRIT_FAILURE, "resolv_get_sockaddr_address failed.\n");
         ret = EIO;
@@ -951,8 +963,12 @@ ad_resolve_callback(void *private_data, struct fo_server *server)
     talloc_zfree(service->gc->uri);
     talloc_zfree(service->gc->sockaddr);
     if (sdata && sdata->gc) {
-        new_port = fo_get_server_port(server);
-        new_port = (new_port == 0) ? AD_GC_PORT : new_port;
+        if (service->gc_port == AD_GC_LDAPS_PORT) {
+            new_port = service->gc_port;
+        } else {
+            new_port = fo_get_server_port(server);
+            new_port = (new_port == 0) ? service->gc_port : new_port;
+        }
 
         service->gc->uri = talloc_asprintf(service->gc, "%s:%d",
                                            new_uri, new_port);
diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h
index 36366e3292..44da58fa0b 100644
--- a/src/providers/ad/ad_common.h
+++ b/src/providers/ad/ad_common.h
@@ -29,7 +29,8 @@
 #define AD_SERVICE_NAME    "AD"
 #define AD_GC_SERVICE_NAME "AD_GC"
 /* The port the Global Catalog runs on */
-#define AD_GC_PORT      3268
+#define AD_GC_PORT         3268
+#define AD_GC_LDAPS_PORT   3269
 
 #define AD_AT_OBJECT_SID "objectSID"
 #define AD_AT_DNS_DOMAIN "DnsDomain"
@@ -68,6 +69,7 @@ enum ad_basic_opt {
     AD_MAXIMUM_MACHINE_ACCOUNT_PASSWORD_AGE,
     AD_MACHINE_ACCOUNT_PASSWORD_RENEWAL_OPTS,
     AD_UPDATE_SAMBA_MACHINE_ACCOUNT_PASSWORD,
+    AD_USE_LDAPS,
 
     AD_OPTS_BASIC /* opts counter */
 };
@@ -83,6 +85,9 @@ struct ad_service {
     struct sdap_service *sdap;
     struct sdap_service *gc;
     struct krb5_service *krb5_service;
+    const char *ldap_scheme;
+    int port;
+    int gc_port;
 };
 
 struct ad_options {
@@ -148,6 +153,7 @@ ad_failover_init(TALLOC_CTX *mem_ctx, struct be_ctx *ctx,
                  const char *ad_gc_service,
                  const char *ad_domain,
                  bool use_kdcinfo,
+                 bool ad_use_ldaps,
                  size_t n_lookahead_primary,
                  size_t n_lookahead_backup,
                  struct ad_service **_service);
diff --git a/src/providers/ad/ad_init.c b/src/providers/ad/ad_init.c
index 290d5b5c1f..2b4b9e2e70 100644
--- a/src/providers/ad/ad_init.c
+++ b/src/providers/ad/ad_init.c
@@ -138,6 +138,7 @@ static errno_t ad_init_options(TALLOC_CTX *mem_ctx,
     char *ad_servers = NULL;
     char *ad_backup_servers = NULL;
     char *ad_realm;
+    bool ad_use_ldaps = false;
     errno_t ret;
 
     ad_sasl_initialize();
@@ -154,12 +155,14 @@ static errno_t ad_init_options(TALLOC_CTX *mem_ctx,
     ad_servers = dp_opt_get_string(ad_options->basic, AD_SERVER);
     ad_backup_servers = dp_opt_get_string(ad_options->basic, AD_BACKUP_SERVER);
     ad_realm = dp_opt_get_string(ad_options->basic, AD_KRB5_REALM);
+    ad_use_ldaps = dp_opt_get_bool(ad_options->basic, AD_USE_LDAPS);
 
     /* Set up the failover service */
     ret = ad_failover_init(ad_options, be_ctx, ad_servers, ad_backup_servers,
                            ad_realm, AD_SERVICE_NAME, AD_GC_SERVICE_NAME,
                            dp_opt_get_string(ad_options->basic, AD_DOMAIN),
                            false, /* will be set in ad_get_auth_options() */
+                           ad_use_ldaps,
                            (size_t) -1,
                            (size_t) -1,
                            &ad_options->service);
@@ -184,11 +187,13 @@ static errno_t ad_init_srv_plugin(struct be_ctx *be_ctx,
     const char *ad_site_override;
     bool sites_enabled;
     errno_t ret;
+    bool ad_use_ldaps;
 
     hostname = dp_opt_get_string(ad_options->basic, AD_HOSTNAME);
     ad_domain = dp_opt_get_string(ad_options->basic, AD_DOMAIN);
     ad_site_override = dp_opt_get_string(ad_options->basic, AD_SITE);
     sites_enabled = dp_opt_get_bool(ad_options->basic, AD_ENABLE_DNS_SITES);
+    ad_use_ldaps = dp_opt_get_bool(ad_options->basic, AD_USE_LDAPS);
 
 
     if (!sites_enabled) {
@@ -205,7 +210,8 @@ static errno_t ad_init_srv_plugin(struct be_ctx *be_ctx,
     srv_ctx = ad_srv_plugin_ctx_init(be_ctx, be_ctx, be_ctx->be_res,
                                      default_host_dbs, ad_options->id,
                                      hostname, ad_domain,
-                                     ad_site_override);
+                                     ad_site_override,
+                                     ad_use_ldaps);
     if (srv_ctx == NULL) {
         DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?\n");
         return ENOMEM;
diff --git a/src/providers/ad/ad_opts.c b/src/providers/ad/ad_opts.c
index de134927e7..26420d6554 100644
--- a/src/providers/ad/ad_opts.c
+++ b/src/providers/ad/ad_opts.c
@@ -55,6 +55,7 @@ struct dp_option ad_basic_opts[] = {
     { "ad_maximum_machine_account_password_age", DP_OPT_NUMBER, { .number = 30 }, NULL_NUMBER },
     { "ad_machine_account_password_renewal_opts", DP_OPT_STRING, { "86400:750" }, NULL_STRING },
     { "ad_update_samba_machine_account_password", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
+    { "ad_use_ldaps", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE },
     DP_OPTION_TERMINATOR
 };
 
diff --git a/src/providers/ad/ad_srv.c b/src/providers/ad/ad_srv.c
index 5fd25f60e8..ca15d3715a 100644
--- a/src/providers/ad/ad_srv.c
+++ b/src/providers/ad/ad_srv.c
@@ -244,6 +244,7 @@ struct ad_get_client_site_state {
     enum host_database *host_db;
     struct sdap_options *opts;
     const char *ad_domain;
+    bool ad_use_ldaps;
     struct fo_server_info *dcs;
     size_t num_dcs;
     size_t dc_index;
@@ -264,6 +265,7 @@ struct tevent_req *ad_get_client_site_send(TALLOC_CTX *mem_ctx,
                                            enum host_database *host_db,
                                            struct sdap_options *opts,
                                            const char *ad_domain,
+                                           bool ad_use_ldaps,
                                            struct fo_server_info *dcs,
                                            size_t num_dcs)
 {
@@ -288,6 +290,7 @@ struct tevent_req *ad_get_client_site_send(TALLOC_CTX *mem_ctx,
     state->host_db = host_db;
     state->opts = opts;
     state->ad_domain = ad_domain;
+    state->ad_use_ldaps = ad_use_ldaps;
     state->dcs = dcs;
     state->num_dcs = num_dcs;
 
@@ -331,8 +334,11 @@ static errno_t ad_get_client_site_next_dc(struct tevent_req *req)
     subreq = sdap_connect_host_send(state, state->ev, state->opts,
                                     state->be_res->resolv,
                                     state->be_res->family_order,
-                                    state->host_db, "ldap", state->dc.host,
-                                    state->dc.port, false);
+                                    state->host_db,
+                                    state->ad_use_ldaps ? "ldaps" : "ldap",
+                                    state->dc.host,
+                                    state->ad_use_ldaps ? 636 : state->dc.port,
+                                    false);
     if (subreq == NULL) {
         ret = ENOMEM;
         goto done;
@@ -491,6 +497,7 @@ struct ad_srv_plugin_ctx {
     const char *ad_domain;
     const char *ad_site_override;
     const char *current_site;
+    bool ad_use_ldaps;
 };
 
 struct ad_srv_plugin_ctx *
@@ -501,7 +508,8 @@ ad_srv_plugin_ctx_init(TALLOC_CTX *mem_ctx,
                        struct sdap_options *opts,
                        const char *hostname,
                        const char *ad_domain,
-                       const char *ad_site_override)
+                       const char *ad_site_override,
+                       bool ad_use_ldaps)
 {
     struct ad_srv_plugin_ctx *ctx = NULL;
     errno_t ret;
@@ -515,6 +523,7 @@ ad_srv_plugin_ctx_init(TALLOC_CTX *mem_ctx,
     ctx->be_res = be_res;
     ctx->host_dbs = host_dbs;
     ctx->opts = opts;
+    ctx->ad_use_ldaps = ad_use_ldaps;
 
     ctx->hostname = talloc_strdup(ctx, hostname);
     if (ctx->hostname == NULL) {
@@ -714,6 +723,7 @@ static void ad_srv_plugin_dcs_done(struct tevent_req *subreq)
                                      state->ctx->host_dbs,
                                      state->ctx->opts,
                                      state->discovery_domain,
+                                     state->ctx->ad_use_ldaps,
                                      dcs, num_dcs);
     if (subreq == NULL) {
         ret = ENOMEM;
diff --git a/src/providers/ad/ad_srv.h b/src/providers/ad/ad_srv.h
index e553d594d7..8e410ec269 100644
--- a/src/providers/ad/ad_srv.h
+++ b/src/providers/ad/ad_srv.h
@@ -31,7 +31,8 @@ ad_srv_plugin_ctx_init(TALLOC_CTX *mem_ctx,
                        struct sdap_options *opts,
                        const char *hostname,
                        const char *ad_domain,
-                       const char *ad_site_override);
+                       const char *ad_site_override,
+                       bool ad_use_ldaps);
 
 struct tevent_req *ad_srv_plugin_send(TALLOC_CTX *mem_ctx,
                                        struct tevent_context *ev,
diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
index 2ce34489f6..d8c2014374 100644
--- a/src/providers/ad/ad_subdomains.c
+++ b/src/providers/ad/ad_subdomains.c
@@ -282,6 +282,7 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
     bool use_kdcinfo = false;
     size_t n_lookahead_primary = SSS_KRB5_LOOKAHEAD_PRIMARY_DEFAULT;
     size_t n_lookahead_backup = SSS_KRB5_LOOKAHEAD_BACKUP_DEFAULT;
+    bool ad_use_ldaps = false;
 
     realm = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_KRB5_REALM);
     hostname = dp_opt_get_cstring(id_ctx->ad_options->basic, AD_HOSTNAME);
@@ -312,6 +313,21 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
         return ENOMEM;
     }
 
+    ret = ad_inherit_opts_if_needed(id_ctx->ad_options->basic,
+                                    ad_options->basic,
+                                    be_ctx->cdb, subdom_conf_path,
+                                    AD_USE_LDAPS);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "Failed to inherit option [%s] to sub-domain [%s]. "
+              "This error is ignored but might cause issues or unexpected "
+              "behavior later on.\n",
+              id_ctx->ad_options->basic[AD_USE_LDAPS].opt_name,
+              subdom->name);
+
+        return ret;
+    }
+
     ret = ad_inherit_opts_if_needed(id_ctx->sdap_id_ctx->opts->basic,
                                     ad_options->id->basic,
                                     be_ctx->cdb, subdom_conf_path,
@@ -344,6 +360,7 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
 
     servers = dp_opt_get_string(ad_options->basic, AD_SERVER);
     backup_servers = dp_opt_get_string(ad_options->basic, AD_BACKUP_SERVER);
+    ad_use_ldaps = dp_opt_get_bool(ad_options->basic, AD_USE_LDAPS);
 
     if (id_ctx->ad_options->auth_ctx != NULL
             && id_ctx->ad_options->auth_ctx->opts != NULL) {
@@ -362,7 +379,7 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
 
     ret = ad_failover_init(ad_options, be_ctx, servers, backup_servers,
                            subdom->realm, service_name, gc_service_name,
-                           subdom->name, use_kdcinfo,
+                           subdom->name, use_kdcinfo, ad_use_ldaps,
                            n_lookahead_primary,
                            n_lookahead_backup,
                            &ad_options->service);
@@ -386,7 +403,7 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
                                      ad_id_ctx->ad_options->id,
                                      hostname,
                                      ad_domain,
-                                     ad_site_override);
+                                     ad_site_override, ad_use_ldaps);
     if (srv_ctx == NULL) {
         DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?\n");
         return ENOMEM;
diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c
index fd998877b3..9aebf72a5a 100644
--- a/src/providers/ipa/ipa_subdomains_server.c
+++ b/src/providers/ipa/ipa_subdomains_server.c
@@ -319,7 +319,7 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx,
     ret = ad_failover_init(ad_options, be_ctx, ad_servers, ad_backup_servers,
                            subdom->realm,
                            service_name, gc_service_name,
-                           subdom->name, use_kdcinfo,
+                           subdom->name, use_kdcinfo, false,
                            n_lookahead_primary, n_lookahead_backup,
                            &ad_options->service);
     if (ret != EOK) {
@@ -344,7 +344,7 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx,
                                      ad_id_ctx->ad_options->id,
                                      id_ctx->server_mode->hostname,
                                      ad_domain,
-                                     ad_site_override);
+                                     ad_site_override, false);
     if (srv_ctx == NULL) {
         DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?\n");
         return ENOMEM;

From 3b95c39819591428b1e535e5dc874268cf5630c5 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Fri, 27 Sep 2019 11:49:59 +0200
Subject: [PATCH 3/4] ldap: add new option ldap_sasl_maxssf

There is already the ldap_sasl_minssf option. To be able to control the
maximal security strength factor (ssf) e.g. when using SASL together
with TLS the option ldap_sasl_maxssf is added as well.

Related to https://pagure.io/SSSD/sssd/issue/4131
---
 src/config/SSSDConfig/__init__.py.in       |  1 +
 src/config/cfg_rules.ini                   |  1 +
 src/config/etc/sssd.api.d/sssd-ad.conf     |  1 +
 src/config/etc/sssd.api.d/sssd-ipa.conf    |  1 +
 src/config/etc/sssd.api.d/sssd-ldap.conf   |  1 +
 src/man/sssd-ldap.5.xml                    | 16 ++++++++++++++++
 src/providers/ad/ad_opts.c                 |  1 +
 src/providers/ipa/ipa_opts.c               |  1 +
 src/providers/ldap/ldap_opts.c             |  1 +
 src/providers/ldap/sdap.h                  |  1 +
 src/providers/ldap/sdap_async_connection.c | 14 ++++++++++++++
 11 files changed, 39 insertions(+)

diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in
index 6c2a1ce441..b3035fcffb 100644
--- a/src/config/SSSDConfig/__init__.py.in
+++ b/src/config/SSSDConfig/__init__.py.in
@@ -306,6 +306,7 @@ option_strings = {
     'ldap_sasl_authid' : _('Specify the sasl authorization id to use'),
     'ldap_sasl_realm' : _('Specify the sasl authorization realm to use'),
     'ldap_sasl_minssf' : _('Specify the minimal SSF for LDAP sasl authorization'),
+    'ldap_sasl_maxssf' : _('Specify the maximal SSF for LDAP sasl authorization'),
     'ldap_krb5_keytab' : _('Kerberos service keytab'),
     'ldap_krb5_init_creds' : _('Use Kerberos auth for LDAP connection'),
     'ldap_referrals' : _('Follow LDAP referrals'),
diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini
index 478ca9eb43..286443be42 100644
--- a/src/config/cfg_rules.ini
+++ b/src/config/cfg_rules.ini
@@ -665,6 +665,7 @@ option = ldap_sasl_authid
 option = ldap_sasl_canonicalize
 option = ldap_sasl_mech
 option = ldap_sasl_minssf
+option = ldap_sasl_maxssf
 option = ldap_schema
 option = ldap_pwmodify_mode
 option = ldap_search_base
diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf
index 51cdad536e..4d10e69d73 100644
--- a/src/config/etc/sssd.api.d/sssd-ad.conf
+++ b/src/config/etc/sssd.api.d/sssd-ad.conf
@@ -42,6 +42,7 @@ ldap_tls_reqcert = str, None, false
 ldap_sasl_mech = str, None, false
 ldap_sasl_authid = str, None, false
 ldap_sasl_minssf = int, None, false
+ldap_sasl_maxssf = int, None, false
 krb5_kdcip = str, None, false
 krb5_server = str, None, false
 krb5_backup_server = str, None, false
diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf
index 7ed153d363..839f9f4716 100644
--- a/src/config/etc/sssd.api.d/sssd-ipa.conf
+++ b/src/config/etc/sssd.api.d/sssd-ipa.conf
@@ -32,6 +32,7 @@ ldap_tls_reqcert = str, None, false
 ldap_sasl_mech = str, None, false
 ldap_sasl_authid = str, None, false
 ldap_sasl_minssf = int, None, false
+ldap_sasl_maxssf = int, None, false
 krb5_kdcip = str, None, false
 krb5_server = str, None, false
 krb5_backup_server = str, None, false
diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf b/src/config/etc/sssd.api.d/sssd-ldap.conf
index 4f73e901e9..6db9828b9d 100644
--- a/src/config/etc/sssd.api.d/sssd-ldap.conf
+++ b/src/config/etc/sssd.api.d/sssd-ldap.conf
@@ -35,6 +35,7 @@ ldap_page_size = int, None, false
 ldap_deref_threshold = int, None, false
 ldap_sasl_canonicalize = bool, None, false
 ldap_sasl_minssf = int, None, false
+ldap_sasl_maxssf = int, None, false
 ldap_connection_expire_timeout = int, None, false
 ldap_connection_expire_offset = int, None, false
 ldap_disable_paging = bool, None, false
diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
index f8bb973c7a..0dc6754109 100644
--- a/src/man/sssd-ldap.5.xml
+++ b/src/man/sssd-ldap.5.xml
@@ -612,6 +612,22 @@
                     </listitem>
                 </varlistentry>
 
+                <varlistentry>
+                    <term>ldap_sasl_maxssf (integer)</term>
+                    <listitem>
+                        <para>
+                            When communicating with an LDAP server using SASL,
+                            specify the maximal security level necessary to
+                            establish the connection. The values of this
+                            option are defined by OpenLDAP.
+                        </para>
+                        <para>
+                            Default: Use the system default (usually specified
+                            by ldap.conf)
+                        </para>
+                    </listitem>
+                </varlistentry>
+
                 <varlistentry>
                     <term>ldap_deref_threshold (integer)</term>
                     <listitem>
diff --git a/src/providers/ad/ad_opts.c b/src/providers/ad/ad_opts.c
index 26420d6554..e9a3dd6ef5 100644
--- a/src/providers/ad/ad_opts.c
+++ b/src/providers/ad/ad_opts.c
@@ -106,6 +106,7 @@ struct dp_option ad_def_ldap_opts[] = {
     { "ldap_sasl_authid", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_sasl_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_sasl_minssf", DP_OPT_NUMBER, { .number = -1 }, NULL_NUMBER },
+    { "ldap_sasl_maxssf", DP_OPT_NUMBER, { .number = -1 }, NULL_NUMBER },
     { "ldap_krb5_keytab", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_krb5_init_creds", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
     /* use the same parm name as the krb5 module so we set it only once */
diff --git a/src/providers/ipa/ipa_opts.c b/src/providers/ipa/ipa_opts.c
index 4fafa073da..55de6e600e 100644
--- a/src/providers/ipa/ipa_opts.c
+++ b/src/providers/ipa/ipa_opts.c
@@ -114,6 +114,7 @@ struct dp_option ipa_def_ldap_opts[] = {
     { "ldap_sasl_authid", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_sasl_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_sasl_minssf", DP_OPT_NUMBER, { .number = 56 }, NULL_NUMBER },
+    { "ldap_sasl_maxssf", DP_OPT_NUMBER, { .number = -1 }, NULL_NUMBER },
     { "ldap_krb5_keytab", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_krb5_init_creds", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
     /* use the same parm name as the krb5 module so we set it only once */
diff --git a/src/providers/ldap/ldap_opts.c b/src/providers/ldap/ldap_opts.c
index ffd0c6baa2..d1b4e98ad5 100644
--- a/src/providers/ldap/ldap_opts.c
+++ b/src/providers/ldap/ldap_opts.c
@@ -74,6 +74,7 @@ struct dp_option default_basic_opts[] = {
     { "ldap_sasl_authid", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_sasl_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_sasl_minssf", DP_OPT_NUMBER, { .number = -1 }, NULL_NUMBER },
+    { "ldap_sasl_maxssf", DP_OPT_NUMBER, { .number = -1 }, NULL_NUMBER },
     { "ldap_krb5_keytab", DP_OPT_STRING, NULL_STRING, NULL_STRING },
     { "ldap_krb5_init_creds", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
     /* use the same parm name as the krb5 module so we set it only once */
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index f27b3c4806..808a2c400f 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -192,6 +192,7 @@ enum sdap_basic_opt {
     SDAP_SASL_AUTHID,
     SDAP_SASL_REALM,
     SDAP_SASL_MINSSF,
+    SDAP_SASL_MAXSSF,
     SDAP_KRB5_KEYTAB,
     SDAP_KRB5_KINIT,
     SDAP_KRB5_KDC,
diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
index 7438d14a7f..5f69cedcc6 100644
--- a/src/providers/ldap/sdap_async_connection.c
+++ b/src/providers/ldap/sdap_async_connection.c
@@ -148,6 +148,8 @@ static void sdap_sys_connect_done(struct tevent_req *subreq)
     const char *sasl_mech;
     int sasl_minssf;
     ber_len_t ber_sasl_minssf;
+    int sasl_maxssf;
+    ber_len_t ber_sasl_maxssf;
 
     ret = sss_ldap_init_recv(subreq, &state->sh->ldap, &sd);
     talloc_zfree(subreq);
@@ -291,6 +293,18 @@ static void sdap_sys_connect_done(struct tevent_req *subreq)
                 goto fail;
             }
         }
+
+        sasl_maxssf = dp_opt_get_int(state->opts->basic, SDAP_SASL_MAXSSF);
+        if (sasl_maxssf >= 0) {
+            ber_sasl_maxssf = (ber_len_t)sasl_maxssf;
+            lret = ldap_set_option(state->sh->ldap, LDAP_OPT_X_SASL_SSF_MAX,
+                                   &ber_sasl_maxssf);
+            if (lret != LDAP_OPT_SUCCESS) {
+                DEBUG(SSSDBG_CRIT_FAILURE, "Failed to set LDAP MAX SSF option "
+                                            "to %d\n", sasl_maxssf);
+                goto fail;
+            }
+        }
     }
 
     /* if we do not use start_tls the connection is not really connected yet

From 50a92f65c4823d272240ef416f2b05874b2b7918 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sb...@redhat.com>
Date: Fri, 27 Sep 2019 13:45:13 +0200
Subject: [PATCH 4/4] ad: set min and max ssf for ldaps

AD does not allow to use encryption in the TLS and SASL layer at the
same time. To be able to use ldaps this patch sets min and max ssf to 0
if ldaps should be used.

Related to https://pagure.io/SSSD/sssd/issue/4131
---
 src/providers/ad/ad_common.c     | 21 +++++++++++++++++++++
 src/providers/ad/ad_common.h     |  2 ++
 src/providers/ad/ad_subdomains.c |  4 ++++
 3 files changed, 27 insertions(+)

diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c
index a2369166a2..51300f5b2a 100644
--- a/src/providers/ad/ad_common.c
+++ b/src/providers/ad/ad_common.c
@@ -1021,6 +1021,23 @@ ad_resolve_callback(void *private_data, struct fo_server *server)
     return;
 }
 
+void ad_set_ssf_for_ldaps(struct sdap_options *id_opts)
+{
+    int ret;
+
+    DEBUG(SSSDBG_TRACE_ALL, "Setting ssf for ldaps usage.\n");
+    ret = dp_opt_set_int(id_opts->basic, SDAP_SASL_MINSSF, 0);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "Failed to set SASL minssf for ldaps usage, ignored.\n");
+    }
+    ret = dp_opt_set_int(id_opts->basic, SDAP_SASL_MAXSSF, 0);
+    if (ret != EOK) {
+        DEBUG(SSSDBG_CRIT_FAILURE,
+              "Failed to set SASL maxssf for ldaps usage, ignored.\n");
+    }
+}
+
 static errno_t
 ad_set_sdap_options(struct ad_options *ad_opts,
                     struct sdap_options *id_opts)
@@ -1079,6 +1096,10 @@ ad_set_sdap_options(struct ad_options *ad_opts,
         goto done;
     }
 
+    if (dp_opt_get_bool(ad_opts->basic, AD_USE_LDAPS)) {
+        ad_set_ssf_for_ldaps(id_opts);
+    }
+
     /* Warn if the user is doing something silly like overriding the schema
      * with the AD provider
      */
diff --git a/src/providers/ad/ad_common.h b/src/providers/ad/ad_common.h
index 44da58fa0b..8b7a86102f 100644
--- a/src/providers/ad/ad_common.h
+++ b/src/providers/ad/ad_common.h
@@ -182,6 +182,8 @@ errno_t
 ad_get_dyndns_options(struct be_ctx *be_ctx,
                       struct ad_options *ad_opts);
 
+void ad_set_ssf_for_ldaps(struct sdap_options *id_opts);
+
 struct ad_id_ctx *
 ad_id_ctx_init(struct ad_options *ad_opts, struct be_ctx *bectx);
 
diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c
index d8c2014374..a9c6b9f287 100644
--- a/src/providers/ad/ad_subdomains.c
+++ b/src/providers/ad/ad_subdomains.c
@@ -328,6 +328,10 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx,
         return ret;
     }
 
+    if (dp_opt_get_bool(ad_options->basic, AD_USE_LDAPS)) {
+        ad_set_ssf_for_ldaps(ad_options->id);
+    }
+
     ret = ad_inherit_opts_if_needed(id_ctx->sdap_id_ctx->opts->basic,
                                     ad_options->id->basic,
                                     be_ctx->cdb, subdom_conf_path,
_______________________________________________
sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org
To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/sssd-devel@lists.fedorahosted.org

Reply via email to