diff --git a/SOURCES/0044-pam_sss_gss-support-authentication-indicators.patch b/SOURCES/0044-pam_sss_gss-support-authentication-indicators.patch
new file mode 100644
index 0000000..91d15c4
--- /dev/null
+++ b/SOURCES/0044-pam_sss_gss-support-authentication-indicators.patch
@@ -0,0 +1,655 @@
+From c2e8879189ecbbdfdd4b42395319a4cd91cb569f Mon Sep 17 00:00:00 2001
+From: Alexey Tikhonov <atikhono@redhat.com>
+Date: Fri, 12 Feb 2021 20:02:52 +0100
+Subject: [PATCH] pam_sss_gss: support authentication indicators (upstream
+patch 5ce7ced269c7b3dd8f75122a50f539083b5697ae by Alexander Bokovoy)
+
+MIT Kerberos allows to associate authentication indicators with the
+issued ticket based on the way how the TGT was obtained. The indicators
+present in the TGT then copied to service tickets. There are two ways to
+check the authentication indicators:
+
+ - when KDC issues a service ticket, a policy at KDC side can reject the
+   ticket issuance based on a lack of certain indicator
+
+ - when a server application presented with a service ticket from a
+   client, it can verify that this ticket contains intended
+   authentication indicators before authorizing access from the client.
+
+Add support to validate presence of a specific (set of) authentication
+indicator(s) in pam_sss_gss when validating a user's TGT.
+
+This concept can be used to only allow access to a PAM service when user
+is in possession of a ticket obtained using some of pre-authentication
+mechanisms that require multiple factors: smart-cards (PKINIT), 2FA
+tokens (otp/radius), etc.
+
+Patch by: Alexander Bokovoy <abokovoy@redhat.com>
+
+Reviewed by: Sumit Bose <sbose@redhat.com>
+
+Adapted to 8.4 branch by: Alexey Tikhonov <atikhono@redhat.com>
+---
+ src/confdb/confdb.c                  |  13 ++
+ src/confdb/confdb.h                  |   3 +
+ src/config/SSSDConfig/sssdoptions.py |   2 +
+ src/config/SSSDConfigTest.py         |   6 +-
+ src/config/cfg_rules.ini             |   3 +
+ src/config/etc/sssd.api.conf         |   2 +
+ src/db/sysdb_subdomains.c            |  12 ++
+ src/man/pam_sss_gss.8.xml            |  13 ++
+ src/man/sssd.conf.5.xml              |  64 +++++++
+ src/responder/pam/pamsrv.c           |  21 +++
+ src/responder/pam/pamsrv.h           |   2 +
+ src/responder/pam/pamsrv_gssapi.c    | 250 +++++++++++++++++++++++++++
+ 12 files changed, 389 insertions(+), 2 deletions(-)
+
+diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c
+index befcfff..cca7615 100644
+--- a/src/confdb/confdb.c
++++ b/src/confdb/confdb.c
+@@ -1603,6 +1603,19 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb,
+         }
+     }
+ 
++    tmp = ldb_msg_find_attr_as_string(res->msgs[0],
++                                      CONFDB_PAM_GSSAPI_INDICATORS_MAP,
++                                      NULL);
++    if (tmp != NULL && tmp[0] != '\0') {
++        ret = split_on_separator(domain, tmp, ',', true, true,
++                                 &domain->gssapi_indicators_map, NULL);
++        if (ret != 0) {
++            DEBUG(SSSDBG_FATAL_FAILURE,
++                  "Cannot parse %s\n", CONFDB_PAM_GSSAPI_INDICATORS_MAP);
++            goto done;
++        }
++    }
++
+     domain->has_views = false;
+     domain->view_name = NULL;
+ 
+diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
+index 036f9ec..a2be227 100644
+--- a/src/confdb/confdb.h
++++ b/src/confdb/confdb.h
+@@ -146,6 +146,7 @@
+ #define CONFDB_PAM_INITGROUPS_SCHEME "pam_initgroups_scheme"
+ #define CONFDB_PAM_GSSAPI_SERVICES "pam_gssapi_services"
+ #define CONFDB_PAM_GSSAPI_CHECK_UPN "pam_gssapi_check_upn"
++#define CONFDB_PAM_GSSAPI_INDICATORS_MAP "pam_gssapi_indicators_map"
+ 
+ /* SUDO */
+ #define CONFDB_SUDO_CONF_ENTRY "config/sudo"
+@@ -437,6 +438,8 @@ struct sss_domain_info {
+     /* List of PAM services that are allowed to authenticate with GSSAPI. */
+     char **gssapi_services;
+     char *gssapi_check_upn; /* true | false | NULL */
++    /* List of indicators associated with the specific PAM service */
++    char **gssapi_indicators_map;
+ };
+ 
+ /**
+diff --git a/src/config/SSSDConfig/sssdoptions.py b/src/config/SSSDConfig/sssdoptions.py
+index 5da52a9..0d849bc 100644
+--- a/src/config/SSSDConfig/sssdoptions.py
++++ b/src/config/SSSDConfig/sssdoptions.py
+@@ -106,6 +106,8 @@ class SSSDOptions(object):
+         'pam_initgroups_scheme' : _('When shall the PAM responder force an initgroups request'),
+         'pam_gssapi_services' : _('List of PAM services that are allowed to authenticate with GSSAPI.'),
+         'pam_gssapi_check_upn' : _('Whether to match authenticated UPN with target user'),
++        'pam_gssapi_indicators_map' : _('List of pairs <PAM service>:<authentication indicator> that '
++                                        'must be enforced for PAM access with GSSAPI authentication'),
+ 
+         # [sudo]
+         'sudo_timed': _('Whether to evaluate the time-based attributes in sudo rules'),
+diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py
+index ea4e4f6..d0422df 100755
+--- a/src/config/SSSDConfigTest.py
++++ b/src/config/SSSDConfigTest.py
+@@ -655,7 +655,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
+             'cached_auth_timeout',
+             'auto_private_groups',
+             'pam_gssapi_services',
+-            'pam_gssapi_check_upn']
++            'pam_gssapi_check_upn',
++            'pam_gssapi_indicators_map']
+ 
+         self.assertTrue(type(options) == dict,
+                         "Options should be a dictionary")
+@@ -1034,7 +1035,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
+             'cached_auth_timeout',
+             'auto_private_groups',
+             'pam_gssapi_services',
+-            'pam_gssapi_check_upn']
++            'pam_gssapi_check_upn',
++            'pam_gssapi_indicators_map']
+ 
+         self.assertTrue(type(options) == dict,
+                         "Options should be a dictionary")
+diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini
+index 6642c63..872ceba 100644
+--- a/src/config/cfg_rules.ini
++++ b/src/config/cfg_rules.ini
+@@ -141,6 +141,7 @@ option = p11_uri
+ option = pam_initgroups_scheme
+ option = pam_gssapi_services
+ option = pam_gssapi_check_upn
++option = pam_gssapi_indicators_map
+ 
+ [rule/allowed_sudo_options]
+ validator = ini_allowed_options
+@@ -441,6 +442,7 @@ option = re_expression
+ option = auto_private_groups
+ option = pam_gssapi_services
+ option = pam_gssapi_check_upn
++option = pam_gssapi_indicators_map
+ 
+ #Entry cache timeouts
+ option = entry_cache_user_timeout
+@@ -837,6 +839,7 @@ option = use_fully_qualified_names
+ option = auto_private_groups
+ option = pam_gssapi_services
+ option = pam_gssapi_check_upn
++option = pam_gssapi_indicators_map
+ 
+ [rule/sssd_checks]
+ validator = sssd_checks
+diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf
+index d3cad73..49ced63 100644
+--- a/src/config/etc/sssd.api.conf
++++ b/src/config/etc/sssd.api.conf
+@@ -82,6 +82,7 @@ p11_uri = str, None, false
+ pam_initgroups_scheme = str, None, false
+ pam_gssapi_services = str, None, false
+ pam_gssapi_check_upn = bool, None, false
++pam_gssapi_indicators_map = str, None, false
+ 
+ [sudo]
+ # sudo service
+@@ -203,6 +204,7 @@ re_expression = str, None, false
+ auto_private_groups = str, None, false
+ pam_gssapi_services = str, None, false
+ pam_gssapi_check_upn = bool, None, false
++pam_gssapi_indicators_map = str, None, false
+ 
+ #Entry cache timeouts
+ entry_cache_user_timeout = int, None, false
+diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c
+index 03ba121..2243872 100644
+--- a/src/db/sysdb_subdomains.c
++++ b/src/db/sysdb_subdomains.c
+@@ -185,6 +185,7 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx,
+     dom->override_gid = parent->override_gid;
+ 
+     dom->gssapi_services = parent->gssapi_services;
++    dom->gssapi_indicators_map = parent->gssapi_indicators_map;
+ 
+     if (parent->sysdb == NULL) {
+         DEBUG(SSSDBG_OP_FAILURE, "Missing sysdb context in parent domain.\n");
+@@ -266,6 +267,17 @@ check_subdom_config_file(struct confdb_ctx *confdb,
+         goto done;
+     }
+ 
++    /* allow to set pam_gssapi_indicators_map */
++    ret = confdb_get_string_as_list(confdb, subdomain, sd_conf_path,
++                                    CONFDB_PAM_GSSAPI_INDICATORS_MAP,
++                                    &subdomain->gssapi_indicators_map);
++    if (ret != EOK && ret != ENOENT) {
++        DEBUG(SSSDBG_OP_FAILURE,
++              "Failed to get %s option for the subdomain: %s\n",
++              CONFDB_PAM_GSSAPI_INDICATORS_MAP, subdomain->name);
++        goto done;
++    }
++
+     ret = EOK;
+ done:
+     talloc_free(tmp_ctx);
+diff --git a/src/man/pam_sss_gss.8.xml b/src/man/pam_sss_gss.8.xml
+index ce5b11b..a83369d 100644
+--- a/src/man/pam_sss_gss.8.xml
++++ b/src/man/pam_sss_gss.8.xml
+@@ -70,6 +70,19 @@
+                 <manvolnum>5</manvolnum>
+             </citerefentry> for more details on these options.
+         </para>
++        <para>
++            Some Kerberos deployments allow to assocate authentication
++            indicators with a particular pre-authentication method used to
++            obtain the ticket granting ticket by the user.
++            <command>pam_sss_gss.so</command> allows to enforce presence of
++            authentication indicators in the service tickets before a particular
++            PAM service can be accessed.
++        </para>
++        <para>
++            If <option>pam_gssapi_indicators_map</option> is set in the [pam] or
++            domain section of sssd.conf, then SSSD will perform a check of the
++            presence of any configured indicators in the service ticket.
++        </para>
+     </refsect1>
+ 
+     <refsect1 id='options'>
+diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml
+index 8b330de..3a9955b 100644
+--- a/src/man/sssd.conf.5.xml
++++ b/src/man/sssd.conf.5.xml
+@@ -1770,6 +1770,70 @@ pam_gssapi_services = sudo, sudo-i
+                         </para>
+                     </listitem>
+                 </varlistentry>
++                <varlistentry>
++                    <term>pam_gssapi_indicators_map</term>
++                    <listitem>
++                        <para>
++                           Comma separated list of authentication indicators required
++                           to be present in a Kerberos ticket to access a PAM service
++                           that is allowed to try GSSAPI authentication using
++                           pam_sss_gss.so module.
++                        </para>
++                        <para>
++                           Each element of the list can be either an authentication indicator
++                           name or a pair <quote>service:indicator</quote>. Indicators not
++                           prefixed with the PAM service name will be required to access any
++                           PAM service configured to be used with
++                           <option>pam_gssapi_services</option>. A resulting list of indicators
++                           per PAM service is then checked against indicators in the Kerberos
++                           ticket during authentication by pam_sss_gss.so. Any indicator from the
++                           ticket that matches the resulting list of indicators for the PAM service
++                           would grant access. If none of the indicators in the list match, access
++                           will be denied. If the resulting list of indicators for the PAM service
++                           is empty, the check will not prevent the access.
++                        </para>
++                        <para>
++                           To disable GSSAPI authentication indicator check, set this option
++                           to <quote>-</quote> (dash). To disable the check for a specific PAM
++                           service, add <quote>service:-</quote>.
++                        </para>
++                        <para>
++                           Note: This option can also be set per-domain which
++                           overwrites the value in [pam] section. It can also
++                           be set for trusted domain which overwrites the value
++                           in the domain section.
++                        </para>
++                        <para>
++                            Following authentication indicators are supported by IPA Kerberos deployments:
++                            <itemizedlist>
++                                <listitem>
++                                    <para>pkinit -- pre-authentication using X.509 certificates -- whether stored in files or on smart cards.</para>
++                                </listitem>
++                                <listitem>
++                                    <para>hardened -- SPAKE pre-authentication or any pre-authentication wrapped in a FAST channel.</para>
++                                </listitem>
++                                <listitem>
++                                    <para>radius -- pre-authentication with the help of a RADIUS server.</para>
++                                </listitem>
++                                <listitem>
++                                    <para>otp -- pre-authentication using integrated two-factor authentication (2FA or one-time password, OTP) in IPA.</para>
++                                </listitem>
++                            </itemizedlist>
++                        </para>
++                        <para>
++                            Example: to require access to SUDO services only
++                            for users which obtained their Kerberos tickets
++                            with a X.509 certificate pre-authentication
++                            (PKINIT), set
++                                <programlisting>
++pam_gssapi_indicators_map = sudo:pkinit, sudo-i:pkinit
++                            </programlisting>
++                        </para>
++                        <para>
++                            Default: not set (use of authentication indicators is not required)
++                        </para>
++                    </listitem>
++                </varlistentry>
+             </variablelist>
+         </refsect2>
+ 
+diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c
+index 3904c09..9b4d6c1 100644
+--- a/src/responder/pam/pamsrv.c
++++ b/src/responder/pam/pamsrv.c
+@@ -370,6 +370,27 @@ static int pam_process_init(TALLOC_CTX *mem_ctx,
+         goto done;
+     }
+ 
++    ret = confdb_get_string(pctx->rctx->cdb, pctx, CONFDB_PAM_CONF_ENTRY,
++                            CONFDB_PAM_GSSAPI_INDICATORS_MAP, "-", &tmpstr);
++    if (ret != EOK) {
++        DEBUG(SSSDBG_FATAL_FAILURE,
++              "Failed to determine gssapi services.\n");
++        goto done;
++    }
++    DEBUG(SSSDBG_TRACE_INTERNAL, "Found value [%s] for option [%s].\n", tmpstr,
++                                 CONFDB_PAM_GSSAPI_INDICATORS_MAP);
++
++    if (tmpstr != NULL) {
++        ret = split_on_separator(pctx, tmpstr, ',', true, true,
++                                 &pctx->gssapi_indicators_map, NULL);
++        if (ret != EOK) {
++            DEBUG(SSSDBG_MINOR_FAILURE,
++                  "split_on_separator() failed [%d]: [%s].\n", ret,
++                  sss_strerror(ret));
++            goto done;
++        }
++    }
++
+     /* The responder is initialized. Now tell it to the monitor. */
+     ret = sss_monitor_service_init(rctx, rctx->ev, SSS_BUS_PAM,
+                                    SSS_PAM_SBUS_SERVICE_NAME,
+diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h
+index 3553296..383c7be 100644
+--- a/src/responder/pam/pamsrv.h
++++ b/src/responder/pam/pamsrv.h
+@@ -65,6 +65,8 @@ struct pam_ctx {
+ 
+     /* List of PAM services that are allowed to authenticate with GSSAPI. */
+     char **gssapi_services;
++    /* List of authentication indicators associated with a PAM service */
++    char **gssapi_indicators_map;
+     bool gssapi_check_upn;
+ };
+ 
+diff --git a/src/responder/pam/pamsrv_gssapi.c b/src/responder/pam/pamsrv_gssapi.c
+index 2d05c78..e4da4c4 100644
+--- a/src/responder/pam/pamsrv_gssapi.c
++++ b/src/responder/pam/pamsrv_gssapi.c
+@@ -24,6 +24,7 @@
+ #include <gssapi/gssapi_krb5.h>
+ #include <stdint.h>
+ #include <stdlib.h>
++#include <string.h>
+ #include <talloc.h>
+ #include <ldb.h>
+ 
+@@ -83,6 +84,117 @@ static bool pam_gssapi_should_check_upn(struct pam_ctx *pam_ctx,
+     return pam_ctx->gssapi_check_upn;
+ }
+ 
++static int pam_gssapi_check_indicators(TALLOC_CTX *mem_ctx,
++                                       const char *pam_service,
++                                       char **gssapi_indicators_map,
++                                       char **indicators)
++{
++    char *authind = NULL;
++    size_t pam_len = strlen(pam_service);
++    char **map = gssapi_indicators_map;
++    char **result = NULL;
++    int res;
++
++    authind = talloc_strdup(mem_ctx, "");
++    if (authind == NULL) {
++        return ENOMEM;
++    }
++
++    for (int i = 0; map[i]; i++) {
++        if (map[i][0] == '-') {
++            DEBUG(SSSDBG_TRACE_FUNC,
++                  "Indicators aren't used for [%s]\n",
++                  pam_service);
++            talloc_free(authind);
++            return EOK;
++        }
++        if (!strchr(map[i], ':')) {
++            authind = talloc_asprintf_append(authind, "%s ", map[i]);
++            if (authind == NULL) {
++                /* Since we allocate on pam_ctx, caller will free it */
++                return ENOMEM;
++            }
++            continue;
++        }
++
++        res = strncmp(map[i], pam_service, pam_len);
++        if (res == 0) {
++            if (strlen(map[i]) > pam_len) {
++                if (map[i][pam_len] != ':') {
++                    /* different PAM service, skip it */
++                    continue;
++                }
++
++                if (map[i][pam_len + 1] == '-') {
++                    DEBUG(SSSDBG_TRACE_FUNC,
++                        "Indicators aren't used for [%s]\n",
++                        pam_service);
++                    talloc_free(authind);
++                    return EOK;
++                }
++
++                authind = talloc_asprintf_append(authind, "%s ",
++                                                 map[i] + (pam_len + 1));
++                if (authind == NULL) {
++                    /* Since we allocate on pam_ctx, caller will free it */
++                    return ENOMEM;
++                }
++            } else {
++                DEBUG(SSSDBG_MINOR_FAILURE, "Invalid value for %s: [%s]\n",
++                      CONFDB_PAM_GSSAPI_INDICATORS_MAP, map[i]);
++                talloc_free(authind);
++                return EINVAL;
++            }
++        }
++    }
++
++    res = ENOENT;
++    map = NULL;
++
++    if (authind[0] == '\0') {
++        /* empty list of per-service indicators -> skip */
++        goto done;
++    }
++
++    /* trim a space after the final indicator
++     * to prevent split_on_separator() to fail */
++    authind[strlen(authind) - 1] = '\0';
++
++    res = split_on_separator(mem_ctx, authind, ' ', true, true,
++                             &map, NULL);
++    if (res != 0) {
++        DEBUG(SSSDBG_FATAL_FAILURE,
++            "Cannot parse list of indicators: [%s]\n", authind);
++        res = EINVAL;
++        goto done;
++    }
++
++    res = diff_string_lists(mem_ctx, indicators, map, NULL, NULL, &result);
++    if (res != 0) {
++        DEBUG(SSSDBG_FATAL_FAILURE,"Cannot diff lists of indicators\n");
++        res = EINVAL;
++        goto done;
++    }
++
++    if (result && result[0] != NULL) {
++        for (int i = 0; result[i]; i++) {
++            DEBUG(SSSDBG_TRACE_FUNC,
++                  "indicator [%s] is allowed for PAM service [%s]\n",
++                  result[i], pam_service);
++        }
++        res = EOK;
++        goto done;
++    }
++
++    res = EPERM;
++
++done:
++    talloc_free(result);
++    talloc_free(authind);
++    talloc_free(map);
++    return res;
++}
++
+ static bool pam_gssapi_allowed(struct pam_ctx *pam_ctx,
+                                struct sss_domain_info *domain,
+                                const char *service)
+@@ -385,12 +497,126 @@ static char *gssapi_get_name(TALLOC_CTX *mem_ctx, gss_name_t gss_name)
+     return exported;
+ }
+ 
++#define AUTH_INDICATORS_TAG "auth-indicators"
++
++static char **gssapi_get_indicators(TALLOC_CTX *mem_ctx, gss_name_t gss_name)
++{
++    gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET;
++    int is_mechname;
++    OM_uint32 major;
++    OM_uint32 minor;
++    gss_buffer_desc value = GSS_C_EMPTY_BUFFER;
++    gss_buffer_desc display_value = GSS_C_EMPTY_BUFFER;
++    char *exported = NULL;
++    char **map = NULL;
++    int res;
++
++    major = gss_inquire_name(&minor, gss_name, &is_mechname, NULL, &attrs);
++    if (major != GSS_S_COMPLETE) {
++        DEBUG(SSSDBG_CRIT_FAILURE, "Unable to inquire name\n");
++        return NULL;
++    }
++
++    if (attrs == GSS_C_NO_BUFFER_SET) {
++        DEBUG(SSSDBG_TRACE_FUNC, "No krb5 attributes in the ticket\n");
++        return NULL;
++    }
++
++    exported = talloc_strdup(mem_ctx, "");
++    if (exported == NULL) {
++        DEBUG(SSSDBG_CRIT_FAILURE,
++              "Unable to pre-allocate indicators\n");
++        goto done;
++    }
++
++    for (int i = 0; i < attrs->count; i++) {
++        int authenticated = 0;
++        int complete = 0;
++        int more = -1;
++
++        /* skip anything but auth-indicators */
++        if (strncmp(AUTH_INDICATORS_TAG, attrs->elements[i].value,
++                    sizeof(AUTH_INDICATORS_TAG) - 1) != 0)
++            continue;
++
++        /* retrieve all indicators */
++        while (more != 0) {
++            value.value = NULL;
++            display_value.value = NULL;
++
++            major = gss_get_name_attribute(&minor, gss_name,
++                                            &attrs->elements[i],
++                                            &authenticated,
++                                            &complete, &value,
++                                            &display_value,
++                                            &more);
++            if (major != GSS_S_COMPLETE) {
++                DEBUG(SSSDBG_CRIT_FAILURE,
++                        "Unable to retrieve an attribute\n");
++                goto done;
++            }
++
++            if ((value.value != NULL) && authenticated) {
++                DEBUG(SSSDBG_TRACE_FUNC,
++                        "attribute's [%.*s] value [%.*s] authenticated\n",
++                        (int) attrs->elements[i].length,
++                        (char*) attrs->elements[i].value,
++                        (int) value.length,
++                        (char*) value.value);
++                exported = talloc_asprintf_append(exported, "%.*s ",
++                                                (int) value.length,
++                                                (char*) value.value);
++            }
++
++            if (exported == NULL) {
++                /* Since we allocate on mem_ctx, caller will free
++                 * the previous version of 'exported' */
++                DEBUG(SSSDBG_CRIT_FAILURE,
++                        "Unable to collect an attribute value\n");
++                goto done;
++            }
++            (void) gss_release_buffer(&minor, &value);
++            (void) gss_release_buffer(&minor, &display_value);
++        }
++    }
++
++    if (exported[0] != '\0') {
++        /* trim a space after the final indicator
++         * to prevent split_on_separator() to fail */
++        exported[strlen(exported) - 1] = '\0';
++    } else {
++        /* empty list */
++        goto done;
++    }
++
++    res = split_on_separator(mem_ctx, exported, ' ', true, true,
++                            &map, NULL);
++    if (res != 0) {
++        DEBUG(SSSDBG_FATAL_FAILURE,
++            "Cannot parse list of indicators: [%s]\n", exported);
++        goto done;
++    } else {
++        DEBUG(SSSDBG_TRACE_FUNC, "authentication indicators: [%s]\n",
++              exported);
++    }
++
++done:
++    (void) gss_release_buffer(&minor, &value);
++    (void) gss_release_buffer(&minor, &display_value);
++    (void) gss_release_buffer_set(&minor, &attrs);
++
++    talloc_free(exported);
++    return map;
++}
++
++
+ struct gssapi_state {
+     struct cli_ctx *cli_ctx;
+     struct sss_domain_info *domain;
+     const char *username;
+ 
+     char *authenticated_upn;
++    char **auth_indicators;
+     bool established;
+     gss_ctx_id_t ctx;
+ };
+@@ -568,6 +794,8 @@ gssapi_handshake(struct gssapi_state *state,
+     DEBUG(SSSDBG_TRACE_FUNC, "Security context established with [%s]\n",
+           state->authenticated_upn);
+ 
++    state->auth_indicators = gssapi_get_indicators(state, client_name);
++
+     state->established = true;
+     ret = EOK;
+ 
+@@ -632,6 +860,7 @@ pam_cmd_gssapi_sec_ctx(struct cli_ctx *cli_ctx)
+     const char *domain_name;
+     const char *username;
+     char *target;
++    char **indicators_map = NULL;
+     size_t gss_data_len;
+     uint8_t *gss_data;
+     errno_t ret;
+@@ -699,6 +928,27 @@ pam_cmd_gssapi_sec_ctx(struct cli_ctx *cli_ctx)
+         goto done;
+     }
+ 
++    /* Use map for auth-indicators from the domain, if defined and
++     * fallback to the [pam] section otherwise */
++    indicators_map = domain->gssapi_indicators_map ?
++                     domain->gssapi_indicators_map :
++                     (pam_ctx->gssapi_indicators_map ?
++                      pam_ctx->gssapi_indicators_map : NULL);
++    if (indicators_map != NULL) {
++        ret = pam_gssapi_check_indicators(state,
++                                          pam_service,
++                                          indicators_map,
++                                          state->auth_indicators);
++        DEBUG(SSSDBG_TRACE_FUNC,
++              "Check if acquired service ticket has req. indicators: %d\n",
++              ret);
++        if ((ret == EPERM) || (ret == ENOMEM) || (ret == EINVAL)) {
++            /* skip further checks if denied or no memory,
++             * ENOENT means the check is not applicable */
++            goto done;
++        }
++    }
++
+     if (!pam_gssapi_should_check_upn(pam_ctx, domain)) {
+         /* We are done. */
+         goto done;
+-- 
+2.21.3
+
diff --git a/SOURCES/0045-sudo-do-not-search-by-low-usn-value-to-improve-perfo.patch b/SOURCES/0045-sudo-do-not-search-by-low-usn-value-to-improve-perfo.patch
new file mode 100644
index 0000000..af99e4f
--- /dev/null
+++ b/SOURCES/0045-sudo-do-not-search-by-low-usn-value-to-improve-perfo.patch
@@ -0,0 +1,121 @@
+From b100efbfabd96dcfb2825777b75b9a9dfaacb937 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Fri, 29 Jan 2021 12:41:28 +0100
+Subject: [PATCH] sudo: do not search by low usn value to improve performance
+
+This is a follow up on these two commits.
+
+- 819d70ef6e6fa0e736ebd60a7f8a26f672927d57
+- 6815844daa7701c76e31addbbdff74656cd30bea
+
+The first one improved the search filter little bit to achieve better
+performance, however it also changed the behavior: we started to search
+for `usn >= 1` in the filter if no usn number was known.
+
+This caused issues on OpenLDAP server which was fixed by the second patch.
+However, the fix was wrong and searching by this meaningfully low number
+can cause performance issues depending on how the filter is optimized and
+evaluated on the server.
+
+Now we omit the usn attribute from the filter if there is no meaningful value.
+
+How to test:
+1. Setup LDAP with no sudo rules defined
+2. Make sure that the LDAP server does not support USN or use the following diff
+   to enforce modifyTimestamp (last USN is always available from rootDSE)
+```diff
+
+Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
+---
+ src/providers/ldap/sdap.c              |  4 ++--
+ src/providers/ldap/sdap_sudo_refresh.c |  6 ++++--
+ src/providers/ldap/sdap_sudo_shared.c  | 21 ++++++---------------
+ 3 files changed, 12 insertions(+), 19 deletions(-)
+
+diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
+index 32c0144b9..c853e4dc1 100644
+--- a/src/providers/ldap/sdap.c
++++ b/src/providers/ldap/sdap.c
+@@ -1391,7 +1391,7 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx,
+     last_usn_name = opts->gen_map[SDAP_AT_LAST_USN].name;
+     entry_usn_name = opts->gen_map[SDAP_AT_ENTRY_USN].name;
+     if (rootdse) {
+-        if (last_usn_name) {
++        if (false) {
+             ret = sysdb_attrs_get_string(rootdse,
+                                           last_usn_name, &last_usn_value);
+             if (ret != EOK) {
+@@ -1500,7 +1500,7 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx,
+         }
+     }
+ 
+-    if (!last_usn_name) {
++    if (true) {
+         DEBUG(SSSDBG_FUNC_DATA,
+               "No known USN scheme is supported by this server!\n");
+         if (!entry_usn_name) {
+diff --git a/src/providers/ldap/sdap_sudo_refresh.c b/src/providers/ldap/sdap_sudo_refresh.c
+index ddcb23781..83f944ccf 100644
+--- a/src/providers/ldap/sdap_sudo_refresh.c
++++ b/src/providers/ldap/sdap_sudo_refresh.c
+@@ -181,8 +181,10 @@ struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx,
+     state->sysdb = id_ctx->be->domain->sysdb;
+ 
+     /* Download all rules from LDAP that are newer than usn */
+-    if (srv_opts == NULL || srv_opts->max_sudo_value == 0) {
+-        DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, assuming zero.\n");
++    if (srv_opts == NULL || srv_opts->max_sudo_value == NULL
++         || strcmp(srv_opts->max_sudo_value, "0") == 0) {
++        DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, assuming zero and "
++              "omitting it from the filter.\n");
+         usn = "0";
+         search_filter = talloc_asprintf(state, "(%s=%s)",
+                                         map[SDAP_AT_SUDO_OC].name,
+diff --git a/src/providers/ldap/sdap_sudo_shared.c b/src/providers/ldap/sdap_sudo_shared.c
+index 4f09957ea..75d1bc3d8 100644
+--- a/src/providers/ldap/sdap_sudo_shared.c
++++ b/src/providers/ldap/sdap_sudo_shared.c
+@@ -129,25 +129,17 @@ sdap_sudo_ptask_setup_generic(struct be_ctx *be_ctx,
+ static char *
+ sdap_sudo_new_usn(TALLOC_CTX *mem_ctx,
+                   unsigned long usn,
+-                  const char *leftover,
+-                  bool supports_usn)
++                  const char *leftover)
+ {
+     const char *str = leftover == NULL ? "" : leftover;
+     char *newusn;
+ 
+-    /* This is a fresh start and server uses modifyTimestamp. We need to
+-     * provide proper datetime value. */
+-    if (!supports_usn && usn == 0) {
+-        newusn = talloc_strdup(mem_ctx, "00000101000000Z");
+-        if (newusn == NULL) {
+-            DEBUG(SSSDBG_MINOR_FAILURE, "Unable to change USN value (OOM)!\n");
+-            return NULL;
+-        }
+-
+-        return newusn;
++    /* Current largest USN is unknown so we keep "0" to indicate it. */
++    if (usn == 0) {
++        return talloc_strdup(mem_ctx, "0");
+     }
+ 
+-    /* We increment USN number so that we can later use simplify filter
++    /* We increment USN number so that we can later use simplified filter
+      * (just usn >= last+1 instead of usn >= last && usn != last).
+      */
+     usn++;
+@@ -219,8 +211,7 @@ sdap_sudo_set_usn(struct sdap_server_opts *srv_opts,
+         srv_opts->last_usn = usn_number;
+     }
+ 
+-    newusn = sdap_sudo_new_usn(srv_opts, srv_opts->last_usn, timezone,
+-                               srv_opts->supports_usn);
++    newusn = sdap_sudo_new_usn(srv_opts, srv_opts->last_usn, timezone);
+     if (newusn == NULL) {
+         return;
+     }
+-- 
+2.21.3
+
diff --git a/SOURCES/0046-ldap-fix-modifytimestamp-debugging-leftovers.patch b/SOURCES/0046-ldap-fix-modifytimestamp-debugging-leftovers.patch
new file mode 100644
index 0000000..ae6dfb7
--- /dev/null
+++ b/SOURCES/0046-ldap-fix-modifytimestamp-debugging-leftovers.patch
@@ -0,0 +1,34 @@
+From fff02bbf7967d291ccb019fae741e6591ed8fd41 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
+Date: Fri, 12 Feb 2021 15:30:59 +0100
+Subject: [PATCH] ldap: fix modifytimestamp debugging leftovers
+
+---
+ src/providers/ldap/sdap.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c
+index c853e4dc1..32c0144b9 100644
+--- a/src/providers/ldap/sdap.c
++++ b/src/providers/ldap/sdap.c
+@@ -1391,7 +1391,7 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx,
+     last_usn_name = opts->gen_map[SDAP_AT_LAST_USN].name;
+     entry_usn_name = opts->gen_map[SDAP_AT_ENTRY_USN].name;
+     if (rootdse) {
+-        if (false) {
++        if (last_usn_name) {
+             ret = sysdb_attrs_get_string(rootdse,
+                                           last_usn_name, &last_usn_value);
+             if (ret != EOK) {
+@@ -1500,7 +1500,7 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx,
+         }
+     }
+ 
+-    if (true) {
++    if (!last_usn_name) {
+         DEBUG(SSSDBG_FUNC_DATA,
+               "No known USN scheme is supported by this server!\n");
+         if (!entry_usn_name) {
+-- 
+2.21.3
+
diff --git a/SOURCES/0047-ssh-restore-default-debug-level.patch b/SOURCES/0047-ssh-restore-default-debug-level.patch
new file mode 100644
index 0000000..7b29783
--- /dev/null
+++ b/SOURCES/0047-ssh-restore-default-debug-level.patch
@@ -0,0 +1,49 @@
+From 2d26c95d78cf43798b54ac8c478b8a9ee41cab39 Mon Sep 17 00:00:00 2001
+From: Sumit Bose <sbose@redhat.com>
+Date: Wed, 3 Feb 2021 18:28:29 +0100
+Subject: [PATCH] ssh: restore default debug level
+
+The recent change of the default debug level for the main SSSD
+components affected the ssh helpers sss_ssh_authorizedkeys and
+sss_ssh_knownhostsproxy as well.
+
+To avoid any confusion about unexpected debug messages this patch
+restores to original value for the two helpers.
+
+Resolves: https://github.com/SSSD/sssd/issues/5488
+
+Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
+---
+ src/sss_client/ssh/sss_ssh_authorizedkeys.c  | 2 +-
+ src/sss_client/ssh/sss_ssh_knownhostsproxy.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/sss_client/ssh/sss_ssh_authorizedkeys.c b/src/sss_client/ssh/sss_ssh_authorizedkeys.c
+index 8e80f9663..877c00299 100644
+--- a/src/sss_client/ssh/sss_ssh_authorizedkeys.c
++++ b/src/sss_client/ssh/sss_ssh_authorizedkeys.c
+@@ -32,7 +32,7 @@
+ int main(int argc, const char **argv)
+ {
+     TALLOC_CTX *mem_ctx = NULL;
+-    int pc_debug = SSSDBG_DEFAULT;
++    int pc_debug = SSSDBG_FATAL_FAILURE;
+     const char *pc_domain = NULL;
+     const char *pc_user = NULL;
+     struct poptOption long_options[] = {
+diff --git a/src/sss_client/ssh/sss_ssh_knownhostsproxy.c b/src/sss_client/ssh/sss_ssh_knownhostsproxy.c
+index ad6af81d8..1102fd4ab 100644
+--- a/src/sss_client/ssh/sss_ssh_knownhostsproxy.c
++++ b/src/sss_client/ssh/sss_ssh_knownhostsproxy.c
+@@ -174,7 +174,7 @@ connect_proxy_command(char **args)
+ int main(int argc, const char **argv)
+ {
+     TALLOC_CTX *mem_ctx = NULL;
+-    int pc_debug = SSSDBG_DEFAULT;
++    int pc_debug = SSSDBG_FATAL_FAILURE;
+     int pc_port = 22;
+     const char *pc_domain = NULL;
+     const char *pc_host = NULL;
+-- 
+2.21.3
+
diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec
index 0bc7768..07ea246 100644
--- a/SPECS/sssd.spec
+++ b/SPECS/sssd.spec
@@ -26,7 +26,7 @@
 
 Name: sssd
 Version: 2.4.0
-Release: 7%{?dist}
+Release: 8%{?dist}
 Group: Applications/System
 Summary: System Security Services Daemon
 License: GPLv3+
@@ -77,6 +77,10 @@ Patch0040: 0040-sudo-runas-do-not-add-to-external-groups-in-IPA.patch
 Patch0041: 0041-responders-add-callback-to-schedule_get_domains_task.patch
 Patch0042: 0042-pam-refresh-certificate-maps-at-the-end-of-initial-d.patch
 Patch0043: 0043-SBUS-set-sbus_name-before-dp_init_send.patch
+Patch0044: 0044-pam_sss_gss-support-authentication-indicators.patch
+Patch0045: 0045-sudo-do-not-search-by-low-usn-value-to-improve-perfo.patch
+Patch0046: 0046-ldap-fix-modifytimestamp-debugging-leftovers.patch
+Patch0047: 0047-ssh-restore-default-debug-level.patch
 
 ### Downstream Patches ###
 
@@ -1257,6 +1261,11 @@ fi
                                 %{_libdir}/%{name}/modules/libwbclient.so
 
 %changelog
+* Fri Feb 12 2021 Alexey Tikhonov <atikhono@redhat.com> - 2.4.0-8
+- Resolves: rhbz#1926622 - Add support to verify authentication indicators in pam_sss_gss
+- Resolves: rhbz#1926454 - First smart refresh query contains modifyTimestamp even if the modifyTimestamp is 0.
+- Resolves: rhbz#1893159 - Default debug level should report all errors / failures (additional patch)
+
 * Tue Jan 26 2021 Alexey Tikhonov <atikhono@redhat.com> - 2.4.0-7
 - Resolves: rhbz#1920001 - Do not add '%' to group names already prefixed with '%' in IPA sudo rules
 - Resolves: rhbz#1918433 - sssd unable to lookup certmap rules