From 341ba49b0deb42e17d535744824786c2499656b7 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Jan 13 2020 11:01:32 +0000 Subject: 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 Reviewed-by: Pavel Březina --- diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in index 92e6141..6c2a1ce 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 f7c1d4c..478ca9e 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 33f040c..51cdad5 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 30c7d07..a634d4f 100644 --- a/src/man/sssd-ad.5.xml +++ b/src/man/sssd-ad.5.xml @@ -1032,6 +1032,26 @@ ad_gpo_map_deny = +my_pam_service + ad_use_ldaps (bool) + + + 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. + + + Default: False + + + + + dyndns_update (boolean) diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c index 600e3ce..a236916 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 36366e3..44da58f 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 290d5b5..2b4b9e2 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 de13492..26420d6 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 5fd25f6..ca15d37 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 e553d59..8e410ec 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 2ce3448..d8c2014 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 fd99887..9aebf72 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;