dpward / rpms / sssd

Forked from rpms/sssd 3 years ago
Clone
Blob Blame History Raw
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