summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/Makefile.am3
-rw-r--r--server/config/SSSDConfig.py2
-rw-r--r--server/config/SSSDConfigTest.py6
-rw-r--r--server/config/etc/sssd.api.d/sssd-krb5.conf4
-rw-r--r--server/external/krb5.m43
-rw-r--r--server/man/sssd-ipa.5.xml17
-rw-r--r--server/man/sssd-krb5.5.xml25
-rw-r--r--server/providers/ipa/ipa_common.c2
-rw-r--r--server/providers/krb5/krb5_auth.c74
-rw-r--r--server/providers/krb5/krb5_become_user.c61
-rw-r--r--server/providers/krb5/krb5_child.c148
-rw-r--r--server/providers/krb5/krb5_common.c2
-rw-r--r--server/providers/krb5/krb5_common.h2
-rw-r--r--server/providers/krb5/krb5_utils.h2
-rw-r--r--server/util/sss_krb5.c16
-rw-r--r--server/util/sss_krb5.h2
16 files changed, 326 insertions, 43 deletions
diff --git a/server/Makefile.am b/server/Makefile.am
index 3701ef1a6..d939f524b 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -565,6 +565,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
@@ -592,6 +593,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 = \
@@ -607,6 +609,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 2de9e7a9f..57d39c7b8 100644
--- a/server/config/SSSDConfig.py
+++ b/server/config/SSSDConfig.py
@@ -91,6 +91,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 e54623342..aca1fbd44 100644
--- a/server/config/SSSDConfigTest.py
+++ b/server/config/SSSDConfigTest.py
@@ -424,6 +424,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
'krb5_realm',
'krb5_ccachedir',
'krb5_ccname_template',
+ 'krb5_keytab',
+ 'krb5_validate',
'krb5_auth_timeout'])
options = domain.list_options()
@@ -495,6 +497,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
'krb5_realm',
'krb5_ccachedir',
'krb5_ccname_template',
+ 'krb5_keytab',
+ 'krb5_validate',
'krb5_auth_timeout']
self.assertTrue(type(options) == dict,
@@ -631,6 +635,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase):
'krb5_realm',
'krb5_ccachedir',
'krb5_ccname_template',
+ 'krb5_keytab',
+ 'krb5_validate',
'krb5_auth_timeout'])
options = domain.list_options()
diff --git a/server/config/etc/sssd.api.d/sssd-krb5.conf b/server/config/etc/sssd.api.d/sssd-krb5.conf
index 85067e93a..860f8b893 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 d02732b16..84bb44174 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 31ce824a8..2751591f3 100644
--- a/server/man/sssd-ipa.5.xml
+++ b/server/man/sssd-ipa.5.xml
@@ -94,6 +94,23 @@
</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 this default differs from the
+ traditional kerberos provider backend.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</para>
</refsect1>
diff --git a/server/man/sssd-krb5.5.xml b/server/man/sssd-krb5.5.xml
index 1f86b49cb..1ca283142 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 54044b99c..38e4d53de 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_principal", 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 a02147e45..d3e05e120 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,10 +69,11 @@ 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(uint32_t) + 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;
+ buf->size += sizeof(uint32_t) + kr->pd->newauthtok_size;
}
buf->data = talloc_size(kr, buf->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,17 @@ 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;
+ /* We need to keep the root privileges to read the keytab file if
+ * validation is enabled, otherwise we can drop them here and run
+ * krb5_child with user privileges. */
+ 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 000000000..351f539a3
--- /dev/null
+++ b/server/providers/krb5/krb5_become_user.c
@@ -0,0 +1,61 @@
+/*
+ SSSD
+
+ Kerberos 5 Backend Module -- Utilities
+
+ Authors:
+ Sumit Bose <sbose@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 2630e0f4d..66fccf89f 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,104 @@ 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;
+ krb5_error_code kt_err;
+ 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;
+ }
+
+ /* We look for the first entry from our realm or take the last one */
+ memset(&entry, 0, sizeof(entry));
+ while ((kt_err = krb5_kt_next_entry(kr->ctx, keytab, &entry, &cursor)) == 0) {
+ if (krb5_realm_compare(kr->ctx, entry.principal, kr->princ)) {
+ DEBUG(9, ("Found keytab entry with the realm of the credential.\n"));
+ break;
+ }
+
+ kerr = krb5_free_keytab_entry_contents(kr->ctx, &entry);
+ if (kerr != 0) {
+ DEBUG(1, ("Failed to free keytab entry.\n"));
+ }
+ memset(&entry, 0, sizeof(entry));
+ }
+
+ /* 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 done;
+ }
+
+ /* check if we got any errors from krb5_kt_next_entry */
+ if (kt_err != 0 && kt_err != KRB5_KT_END) {
+ DEBUG(1, ("error reading keytab [%s], not verifying TGT.\n",
+ kr->keytab));
+ goto done;
+ }
+
+ /* 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 done;
+ }
+
+
+ krb5_verify_init_creds_opt_init(&opt);
+ kerr = krb5_verify_init_creds(kr->ctx, kr->creds, entry.principal, keytab,
+ NULL, &opt);
+
+ 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));
+ }
+
+done:
+ if (krb5_kt_close(kr->ctx, keytab) != 0) {
+ DEBUG(1, ("krb5_kt_close failed"));
+ }
+ if (krb5_free_keytab_entry_contents(kr->ctx, &entry) != 0) {
+ DEBUG(1, ("Failed to free keytab entry.\n"));
+ }
+ if (principal != NULL) {
+ sss_krb5_free_unparsed_name(kr->ctx, principal);
+ }
+
+ 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 +305,25 @@ 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;
+ }
+
+ /* We drop root privileges which were needed to read the keytab file
+ * for the validation validation of the credentials here to run the
+ * ccache I/O operations with user privileges. */
+ 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 +582,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 +594,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 +631,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 +807,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 +880,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 +892,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 de069cd28..30878de34 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_principal", 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 60f6a82fb..cb60f425f 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 dec6f7f2f..7637041a6 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 59e278ede..e96e1ba42 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 755cf8165..342196d32 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__ */