[SSSD] [PATCH] Validate Kerberos cerdentials with local keytab

Sumit Bose sbose at redhat.com
Thu Nov 12 11:46:21 UTC 2009


Hi,

this patch add the possibility to validate the credentials obtained from
a Kerberos server with a local keytab. The boolean option krb5_validate
switches the validation on and off. It is disabled by default in the
kerberos provider and enabled by default in the IPA provider.

Typically root privileges are needed to read a keytab. As a consequence
if validation is enabled the privileges cannot be drop before starting
krb5_child, but only after reading the keytab.

bye,
Sumit
-------------- next part --------------
>From c94b74d31afa9361507095cacc6bfb391c23d8a8 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 11 Nov 2009 14:16:41 +0100
Subject: [PATCH] Validate Kerberos cerdentials with local keytab

---
 server/Makefile.am                          |    3 +
 server/config/SSSDConfig.py                 |    2 +
 server/config/SSSDConfigTest.py             |    2 +
 server/config/etc/sssd.api.d/sssd-krb5.conf |    4 +-
 server/external/krb5.m4                     |    3 +-
 server/man/sssd-ipa.5.xml                   |   15 +++
 server/man/sssd-krb5.5.xml                  |   25 +++++
 server/providers/ipa/ipa_common.c           |    2 +
 server/providers/krb5/krb5_auth.c           |   69 +++++++-------
 server/providers/krb5/krb5_become_user.c    |   61 ++++++++++++
 server/providers/krb5/krb5_child.c          |  134 ++++++++++++++++++++++++++-
 server/providers/krb5/krb5_common.c         |    2 +
 server/providers/krb5/krb5_common.h         |    2 +
 server/providers/krb5/krb5_utils.h          |    2 +
 server/util/sss_krb5.c                      |   16 +++-
 server/util/sss_krb5.h                      |    2 +
 16 files changed, 302 insertions(+), 42 deletions(-)
 create mode 100644 server/providers/krb5/krb5_become_user.c

diff --git a/server/Makefile.am b/server/Makefile.am
index 08c0295..6dfc2ae 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -564,6 +564,7 @@ libsss_proxy_la_LDFLAGS = \
 
 libsss_krb5_la_SOURCES = \
     providers/krb5/krb5_utils.c \
+    providers/krb5/krb5_become_user.c \
     providers/krb5/krb5_auth.c \
     providers/krb5/krb5_common.c \
     providers/krb5/krb5_init.c
@@ -591,6 +592,7 @@ libsss_ipa_la_SOURCES = \
     util/sss_ldap.c \
     util/sss_krb5.c \
     providers/krb5/krb5_utils.c \
+    providers/krb5/krb5_become_user.c \
     providers/krb5/krb5_common.c \
     providers/krb5/krb5_auth.c
 libsss_ipa_la_CFLAGS = \
@@ -606,6 +608,7 @@ libsss_ipa_la_LDFLAGS = \
 
 krb5_child_SOURCES = \
     $(SSSD_DEBUG_OBJ) \
+    providers/krb5/krb5_become_user.c \
     providers/krb5/krb5_child.c \
     util/sss_krb5.c
 krb5_child_CFLAGS = \
diff --git a/server/config/SSSDConfig.py b/server/config/SSSDConfig.py
index 1fa6d4c..054333d 100644
--- a/server/config/SSSDConfig.py
+++ b/server/config/SSSDConfig.py
@@ -89,6 +89,8 @@ option_strings = {
     # [provider/krb5/auth]
     'krb5_ccachedir' : _('Directory to store credential caches'),
     'krb5_ccname_template' : _("Location of the user's credential cache"),
+    'krb5_keytab' : _("Location of the keytab to validate credentials"),
+    'krb5_validate' : _("Enable credential validation"),
 
     # [provider/krb5/chpass]
     'krb5_changepw_principal' : _('The principal of the change password service'),
diff --git a/server/config/SSSDConfigTest.py b/server/config/SSSDConfigTest.py
index 944f86f..ae175a3 100644
--- a/server/config/SSSDConfigTest.py
+++ b/server/config/SSSDConfigTest.py
@@ -550,6 +550,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
             'krb5_realm',
             'krb5_ccachedir',
             'krb5_ccname_template',
+            'krb5_keytab',
+            'krb5_validate',
             'krb5_auth_timeout']
 
         self.assertTrue(type(options) == dict,
diff --git a/server/config/etc/sssd.api.d/sssd-krb5.conf b/server/config/etc/sssd.api.d/sssd-krb5.conf
index 85067e9..860f8b8 100644
--- a/server/config/etc/sssd.api.d/sssd-krb5.conf
+++ b/server/config/etc/sssd.api.d/sssd-krb5.conf
@@ -6,8 +6,10 @@ krb5_auth_timeout = int, None
 [provider/krb5/auth]
 krb5_ccachedir = str, None
 krb5_ccname_template = str, None
+krb5_keytab = str, None
+krb5_validate = bool, None
 
 [provider/krb5/access]
 
 [provider/krb5/chpass]
-krb5_changepw_principal = str, None
\ No newline at end of file
+krb5_changepw_principal = str, None
diff --git a/server/external/krb5.m4 b/server/external/krb5.m4
index d02732b..84bb441 100644
--- a/server/external/krb5.m4
+++ b/server/external/krb5.m4
@@ -37,7 +37,8 @@ SAVE_LIBS=$LIBS
 CFLAGS="$CFLAGS $KRB5_CFLAGS"
 LIBS="$LIBS $KRB5_LIBS"
 AC_CHECK_HEADERS([krb5.h krb5/krb5.h])
-AC_CHECK_FUNCS([krb5_get_init_creds_opt_alloc krb5_get_error_message])
+AC_CHECK_FUNCS([krb5_get_init_creds_opt_alloc krb5_get_error_message \
+                krb5_free_unparsed_name])
 CFLAGS=$SAVE_CFLAGS
 LIBS=$SAVE_LIBS
 
diff --git a/server/man/sssd-ipa.5.xml b/server/man/sssd-ipa.5.xml
index 31ce824..88770c8 100644
--- a/server/man/sssd-ipa.5.xml
+++ b/server/man/sssd-ipa.5.xml
@@ -94,6 +94,21 @@
                     </listitem>
                 </varlistentry>
 
+                <varlistentry>
+                    <term>krb5_validate (boolean)</term>
+                    <listitem>
+                        <para>
+                            Verify with the help of krb5_keytab that the TGT obtained has not been spoofed.
+                        </para>
+                        <para>
+                            Default: true
+                        </para>
+                        <para>
+                             Please note that the default of the underlying Kerberos provider is false.
+                        </para>
+                    </listitem>
+                </varlistentry>
+
             </variablelist>
         </para>
     </refsect1>
diff --git a/server/man/sssd-krb5.5.xml b/server/man/sssd-krb5.5.xml
index e90e6f4..18d45ec 100644
--- a/server/man/sssd-krb5.5.xml
+++ b/server/man/sssd-krb5.5.xml
@@ -178,6 +178,31 @@
                     </listitem>
                 </varlistentry>
 
+                <varlistentry>
+                    <term>krb5_validate (boolean)</term>
+                    <listitem>
+                        <para>
+                            Verify with the help of krb5_keytab that the TGT obtained has not been spoofed.
+                        </para>
+                        <para>
+                            Default: false
+                        </para>
+                    </listitem>
+                </varlistentry>
+
+                <varlistentry>
+                    <term>krb5_keytab (string)</term>
+                    <listitem>
+                        <para>
+                            The location of the keytab to use when validating
+                            credentials obtained from KDCs.
+                        </para>
+                        <para>
+                            Default: /etc/krb5.keytab
+                        </para>
+                    </listitem>
+                </varlistentry>
+
             </variablelist>
         </para>
     </refsect1>
diff --git a/server/providers/ipa/ipa_common.c b/server/providers/ipa/ipa_common.c
index 271cc22..ff96fca 100644
--- a/server/providers/ipa/ipa_common.c
+++ b/server/providers/ipa/ipa_common.c
@@ -112,6 +112,8 @@ struct dp_option ipa_def_krb5_opts[] = {
     { "krb5_ccname_template", DP_OPT_STRING, { "FILE:%d/krb5cc_%U_XXXXXX" }, NULL_STRING},
     { "krb5_changepw_princ", DP_OPT_STRING, { "kadmin/changepw" }, NULL_STRING },
     { "krb5_auth_timeout", DP_OPT_NUMBER, { .number = 15 }, NULL_NUMBER },
+    { "krb5_keytab", DP_OPT_STRING, { "/etc/krb5.keytab" }, NULL_STRING },
+    { "krb5_validate", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }
 };
 
 int domain_to_basedn(TALLOC_CTX *memctx, const char *domain, char **basedn)
diff --git a/server/providers/krb5/krb5_auth.c b/server/providers/krb5/krb5_auth.c
index a02147e..de21803 100644
--- a/server/providers/krb5/krb5_auth.c
+++ b/server/providers/krb5/krb5_auth.c
@@ -43,36 +43,6 @@
 #define KRB5_CHILD SSSD_LIBEXEC_PATH"/krb5_child"
 #endif
 
-static errno_t become_user(uid_t uid, gid_t gid)
-{
-    int ret;
-    ret = setgid(gid);
-    if (ret == -1) {
-        DEBUG(1, ("setgid failed [%d][%s].\n", errno, strerror(errno)));
-        return errno;
-    }
-
-    ret = setuid(uid);
-    if (ret == -1) {
-        DEBUG(1, ("setuid failed [%d][%s].\n", errno, strerror(errno)));
-        return errno;
-    }
-
-    ret = setegid(gid);
-    if (ret == -1) {
-        DEBUG(1, ("setegid failed [%d][%s].\n", errno, strerror(errno)));
-        return errno;
-    }
-
-    ret = seteuid(uid);
-    if (ret == -1) {
-        DEBUG(1, ("seteuid failed [%d][%s].\n", errno, strerror(errno)));
-        return errno;
-    }
-
-    return EOK;
-}
-
 struct io_buffer {
     uint8_t *data;
     size_t size;
@@ -82,6 +52,16 @@ errno_t create_send_buffer(struct krb5child_req *kr, struct io_buffer **io_buf)
 {
     struct io_buffer *buf;
     size_t rp;
+    const char *keytab;
+    uint32_t validate;
+
+    keytab = dp_opt_get_cstring(kr->krb5_ctx->opts, KRB5_KEYTAB);
+    if (keytab == NULL) {
+        DEBUG(1, ("Missing keytab option.\n"));
+        return EINVAL;
+    }
+
+    validate = dp_opt_get_bool(kr->krb5_ctx->opts, KRB5_VALIDATE) ? 1 : 0;
 
     buf = talloc(kr, struct io_buffer);
     if (buf == NULL) {
@@ -89,7 +69,8 @@ errno_t create_send_buffer(struct krb5child_req *kr, struct io_buffer **io_buf)
         return ENOMEM;
     }
 
-    buf->size = 4*sizeof(int) + strlen(kr->pd->upn) + strlen(kr->ccname) +
+    buf->size = 8*sizeof(int) + strlen(kr->pd->upn) + strlen(kr->ccname) +
+                strlen(keytab) +
                 kr->pd->authtok_size;
     if (kr->pd->cmd == SSS_PAM_CHAUTHTOK) {
         buf->size += sizeof(int) + kr->pd->newauthtok_size;
@@ -106,6 +87,15 @@ errno_t create_send_buffer(struct krb5child_req *kr, struct io_buffer **io_buf)
     ((uint32_t *)(&buf->data[rp]))[0] = kr->pd->cmd;
     rp += sizeof(uint32_t);
 
+    ((uint32_t *)(&buf->data[rp]))[0] = kr->pd->pw_uid;
+    rp += sizeof(uint32_t);
+
+    ((uint32_t *)(&buf->data[rp]))[0] = kr->pd->gr_gid;
+    rp += sizeof(uint32_t);
+
+    ((uint32_t *)(&buf->data[rp]))[0] = validate;
+    rp += sizeof(uint32_t);
+
     ((uint32_t *)(&buf->data[rp]))[0] = (uint32_t) strlen(kr->pd->upn);
     rp += sizeof(uint32_t);
 
@@ -118,6 +108,12 @@ errno_t create_send_buffer(struct krb5child_req *kr, struct io_buffer **io_buf)
     memcpy(&buf->data[rp], kr->ccname, strlen(kr->ccname));
     rp += strlen(kr->ccname);
 
+    ((uint32_t *)(&buf->data[rp]))[0] = (uint32_t) strlen(keytab);
+    rp += sizeof(uint32_t);
+
+    memcpy(&buf->data[rp], keytab, strlen(keytab));
+    rp += strlen(keytab);
+
     ((uint32_t *)(&buf->data[rp]))[0] = kr->pd->authtok_size;
     rp += sizeof(uint32_t);
 
@@ -436,13 +432,14 @@ static errno_t fork_child(struct krb5child_req *kr)
             return err;
         }
 
-        ret = become_user(kr->pd->pw_uid, kr->pd->gr_gid);
-        if (ret != EOK) {
-            DEBUG(1, ("become_user failed.\n"));
-            return ret;
+        if (!dp_opt_get_bool(kr->krb5_ctx->opts, KRB5_VALIDATE)) {
+            ret = become_user(kr->pd->pw_uid, kr->pd->gr_gid);
+            if (ret != EOK) {
+                DEBUG(1, ("become_user failed.\n"));
+                return ret;
+            }
         }
 
-
         close(pipefd_to_child[1]);
         ret = dup2(pipefd_to_child[0],STDIN_FILENO);
         if (ret == -1) {
diff --git a/server/providers/krb5/krb5_become_user.c b/server/providers/krb5/krb5_become_user.c
new file mode 100644
index 0000000..351f539
--- /dev/null
+++ b/server/providers/krb5/krb5_become_user.c
@@ -0,0 +1,61 @@
+/*
+    SSSD
+
+    Kerberos 5 Backend Module -- Utilities
+
+    Authors:
+        Sumit Bose <sbose at redhat.com>
+
+    Copyright (C) 2009 Red Hat
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "util/util.h"
+
+errno_t become_user(uid_t uid, gid_t gid)
+{
+    int ret;
+
+    DEBUG(9, ("Trying to become user [%d][%d].\n", uid, gid));
+    ret = setgid(gid);
+    if (ret == -1) {
+        DEBUG(1, ("setgid failed [%d][%s].\n", errno, strerror(errno)));
+        return errno;
+    }
+
+    ret = setuid(uid);
+    if (ret == -1) {
+        DEBUG(1, ("setuid failed [%d][%s].\n", errno, strerror(errno)));
+        return errno;
+    }
+
+    ret = setegid(gid);
+    if (ret == -1) {
+        DEBUG(1, ("setegid failed [%d][%s].\n", errno, strerror(errno)));
+        return errno;
+    }
+
+    ret = seteuid(uid);
+    if (ret == -1) {
+        DEBUG(1, ("seteuid failed [%d][%s].\n", errno, strerror(errno)));
+        return errno;
+    }
+
+    return EOK;
+}
+
diff --git a/server/providers/krb5/krb5_child.c b/server/providers/krb5/krb5_child.c
index 2630e0f..1b4ea60 100644
--- a/server/providers/krb5/krb5_child.c
+++ b/server/providers/krb5/krb5_child.c
@@ -88,6 +88,8 @@ struct krb5_req {
     errno_t (*child_req)(int fd, struct krb5_req *kr);
 
     char *ccname;
+    char *keytab;
+    bool validate;
 };
 
 static krb5_context krb5_error_ctx;
@@ -193,10 +195,93 @@ static struct response *prepare_response_message(struct krb5_req *kr,
     return resp;
 }
 
+static krb5_error_code validate_tgt(struct krb5_req *kr)
+{
+    krb5_error_code kerr;
+    char *principal;
+    krb5_keytab keytab;
+    krb5_kt_cursor cursor;
+    krb5_keytab_entry entry;
+    krb5_verify_init_creds_opt opt;
+
+    memset(&keytab, 0, sizeof(keytab));
+    kerr = krb5_kt_resolve(kr->ctx, kr->keytab, &keytab);
+    if (kerr != 0) {
+        DEBUG(1, ("error resolving keytab [%s], not verifying TGT.\n",
+                  kr->keytab));
+        return kerr;
+    }
+
+    memset(&cursor, 0, sizeof(cursor));
+    kerr = krb5_kt_start_seq_get(kr->ctx, keytab, &cursor);
+    if (kerr != 0) {
+        DEBUG(1, ("error reading keytab [%s], not verifying TGT.\n",
+                  kr->keytab));
+        return kerr;
+    }
+
+    memset(&entry, 0, sizeof(entry));
+    kerr = krb5_kt_next_entry(kr->ctx, keytab, &entry, &cursor);
+    if (kerr != 0) {
+        DEBUG(1, ("error reading keytab [%s], not verifying TGT.\n",
+                  kr->keytab));
+        goto fail;
+    }
+
+    /* Get the principal to which the key belongs, for logging purposes. */
+    principal = NULL;
+    kerr = krb5_unparse_name(kr->ctx, entry.principal, &principal);
+    if (kerr != 0) {
+        DEBUG(1, ("internal error parsing principal name, "
+                  "not verifying TGT.\n"));
+        goto fail;
+    }
+
+    /* Close the keytab here.  Even though we're using cursors, the file
+     * handle is stored in the krb5_keytab structure, and it gets
+     * overwritten when the verify_init_creds() call below creates its own
+     * cursor, creating a leak. */
+    kerr = krb5_kt_end_seq_get(kr->ctx, keytab, &cursor);
+    if (kerr != 0) {
+        DEBUG(1, ("krb5_kt_end_seq_get failed, not verifying TGT.\n"));
+        goto close;
+    }
+
+    krb5_verify_init_creds_opt_init(&opt);
+    kerr = krb5_verify_init_creds(kr->ctx, kr->creds, entry.principal, keytab,
+                                  NULL, &opt);
+
+    if (krb5_kt_close(kr->ctx, keytab) != 0) {
+        DEBUG(1, ("krb5_kt_close failed, still trying to verify TGT.\n"));
+    }
+
+    if (kerr == 0) {
+        DEBUG(5, ("TGT verified using key for [%s].\n", principal));
+    } else {
+        DEBUG(1 ,("TGT failed verification using key for [%s].\n", principal));
+    }
+
+    sss_krb5_free_unparsed_name(kr->ctx, principal);
+
+    return kerr;
+
+fail:
+    if (krb5_kt_end_seq_get(kr->ctx, keytab, &cursor) != 0) {
+        DEBUG(1, ("krb5_kt_end_seq_get failed"));
+    }
+close:
+    if (krb5_kt_close(kr->ctx, keytab) != 0) {
+        DEBUG(1, ("krb5_kt_close failed"));
+    }
+    return kerr;
+
+}
+
 static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
                                         char *password)
 {
     krb5_error_code kerr = 0;
+    int ret;
     int fd = -1;
     size_t ccname_len = 0;
     size_t offset = 0;
@@ -209,6 +294,22 @@ static krb5_error_code get_and_save_tgt(struct krb5_req *kr,
         return kerr;
     }
 
+    if (kr->validate) {
+        kerr = validate_tgt(kr);
+        if (kerr != 0) {
+            KRB5_DEBUG(1, kerr);
+            return kerr;
+        }
+
+        ret = become_user(kr->pd->pw_uid, kr->pd->gr_gid);
+        if (ret != EOK) {
+            DEBUG(1, ("become_user failed.\n"));
+            return ret;
+        }
+    } else {
+        DEBUG(9, ("TGT validation is disabled.\n"));
+    }
+
     if (kr->ccname[0] == '/' || strncmp(kr->ccname, "FILE:", 5) == 0) {
         offset = 0;
         if (kr->ccname[0] == 'F') {
@@ -467,7 +568,7 @@ uint8_t *copy_buffer_and_add_zero(TALLOC_CTX *mem_ctx, const uint8_t *src, size_
 }
 
 static errno_t unpack_buffer(uint8_t *buf, size_t size, struct pam_data *pd,
-                             char **ccname)
+                             char **ccname, char **keytab, uint32_t *validate)
 {
     size_t p = 0;
     uint32_t *len;
@@ -479,6 +580,21 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size, struct pam_data *pd,
 
     if ((p + sizeof(uint32_t)) > size) return EINVAL;
     len = ((uint32_t *)(buf+p));
+    pd->pw_uid = *len;
+    p += sizeof(uint32_t);
+
+    if ((p + sizeof(uint32_t)) > size) return EINVAL;
+    len = ((uint32_t *)(buf+p));
+    pd->gr_gid = *len;
+    p += sizeof(uint32_t);
+
+    if ((p + sizeof(uint32_t)) > size) return EINVAL;
+    len = ((uint32_t *)(buf+p));
+    *validate = *len;
+    p += sizeof(uint32_t);
+
+    if ((p + sizeof(uint32_t)) > size) return EINVAL;
+    len = ((uint32_t *)(buf+p));
     p += sizeof(uint32_t);
 
     if ((p + *len ) > size) return EINVAL;
@@ -501,6 +617,16 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size, struct pam_data *pd,
     len = ((uint32_t *)(buf+p));
     p += sizeof(uint32_t);
 
+    if ((p + *len ) > size) return EINVAL;
+    *keytab = (char *) copy_buffer_and_add_zero(pd, buf+p,
+                                                sizeof(char) * (*len));
+    if (*keytab == NULL) return ENOMEM;
+    p += *len;
+
+    if ((p + sizeof(uint32_t)) > size) return EINVAL;
+    len = ((uint32_t *)(buf+p));
+    p += sizeof(uint32_t);
+
     if ((p + *len) > size) return EINVAL;
     pd->authtok = copy_buffer_and_add_zero(pd, buf+p, sizeof(char) * (*len));
     if (pd->authtok == NULL) return ENOMEM;
@@ -667,6 +793,8 @@ int main(int argc, const char *argv[])
     struct pam_data *pd = NULL;
     struct krb5_req *kr = NULL;
     char *ccname;
+    char *keytab;
+    uint32_t validate;
     int opt;
     poptContext pc;
     int debug_fd = -1;
@@ -738,7 +866,7 @@ int main(int argc, const char *argv[])
     }
     close(STDIN_FILENO);
 
-    ret = unpack_buffer(buf, len, pd, &ccname);
+    ret = unpack_buffer(buf, len, pd, &ccname, &keytab, &validate);
     if (ret != EOK) {
         DEBUG(1, ("unpack_buffer failed.\n"));
         goto fail;
@@ -750,6 +878,8 @@ int main(int argc, const char *argv[])
         goto fail;
     }
     kr->ccname = ccname;
+    kr->keytab = keytab;
+    kr->validate = (validate == 0) ? false : true;
 
     ret = kr->child_req(STDOUT_FILENO, kr);
     if (ret != EOK) {
diff --git a/server/providers/krb5/krb5_common.c b/server/providers/krb5/krb5_common.c
index 0657231..4556257 100644
--- a/server/providers/krb5/krb5_common.c
+++ b/server/providers/krb5/krb5_common.c
@@ -35,6 +35,8 @@ struct dp_option default_krb5_opts[] = {
     { "krb5_ccname_template", DP_OPT_STRING, { "FILE:%d/krb5cc_%U_XXXXXX" }, NULL_STRING},
     { "krb5_changepw_principle", DP_OPT_STRING, { "kadmin/changepw" }, NULL_STRING },
     { "krb5_auth_timeout", DP_OPT_NUMBER, { .number = 15 }, NULL_NUMBER },
+    { "krb5_keytab", DP_OPT_STRING, { "/etc/krb5.keytab" }, NULL_STRING },
+    { "krb5_validate", DP_OPT_BOOL, BOOL_FALSE, BOOL_FALSE }
 };
 
 errno_t check_and_export_options(struct dp_option *opts,
diff --git a/server/providers/krb5/krb5_common.h b/server/providers/krb5/krb5_common.h
index 60f6a82..cb60f42 100644
--- a/server/providers/krb5/krb5_common.h
+++ b/server/providers/krb5/krb5_common.h
@@ -44,6 +44,8 @@ enum krb5_opts {
     KRB5_CCNAME_TMPL,
     KRB5_CHANGEPW_PRINC,
     KRB5_AUTH_TIMEOUT,
+    KRB5_KEYTAB,
+    KRB5_VALIDATE,
 
     KRB5_OPTS
 };
diff --git a/server/providers/krb5/krb5_utils.h b/server/providers/krb5/krb5_utils.h
index dec6f7f..7637041 100644
--- a/server/providers/krb5/krb5_utils.h
+++ b/server/providers/krb5/krb5_utils.h
@@ -34,4 +34,6 @@
 char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr,
                              const char *template);
 
+errno_t become_user(uid_t uid, gid_t gid);
+
 #endif /* __KRB5_UTILS_H__ */
diff --git a/server/util/sss_krb5.c b/server/util/sss_krb5.c
index 59e278e..e96e1ba 100644
--- a/server/util/sss_krb5.c
+++ b/server/util/sss_krb5.c
@@ -83,10 +83,22 @@ void KRB5_CALLCONV sss_krb5_get_init_creds_opt_free (krb5_context context,
                                                    krb5_get_init_creds_opt *opt)
 {
 #ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC
-        krb5_get_init_creds_opt_free(context, opt);
+    krb5_get_init_creds_opt_free(context, opt);
 #else
-        free(opt);
+    free(opt);
 #endif
 
     return;
 }
+
+void KRB5_CALLCONV sss_krb5_free_unparsed_name(krb5_context context, char *name)
+{
+#ifdef HAVE_KRB5_FREE_UNPARSED_NAME
+    krb5_free_unparsed_name(context, name);
+#else
+    if (name != NULL) {
+        memset(name, 0, strlen(name));
+        free(name);
+    }
+#endif
+}
diff --git a/server/util/sss_krb5.h b/server/util/sss_krb5.h
index 755cf81..342196d 100644
--- a/server/util/sss_krb5.h
+++ b/server/util/sss_krb5.h
@@ -42,4 +42,6 @@ krb5_error_code KRB5_CALLCONV sss_krb5_get_init_creds_opt_alloc(
 
 void KRB5_CALLCONV sss_krb5_get_init_creds_opt_free (krb5_context context,
                                                   krb5_get_init_creds_opt *opt);
+
+void KRB5_CALLCONV sss_krb5_free_unparsed_name(krb5_context context, char *name);
 #endif /* __SSS_KRB5_H__ */
-- 
1.6.2.5



More information about the sssd-devel mailing list