summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2010-07-20 18:35:50 +0200
committerStephen Gallagher <sgallagh@redhat.com>2010-08-03 13:50:28 -0400
commit2f4e8fbdf1d4ba1e00fcab93af91fe4f4f40250d (patch)
tree555aa8943fe4bf30d52d2dd64bde1fe5692b0b09
parent13d90c2ae8413317947d392c89fffca10ec83587 (diff)
downloadsssd-2f4e8fbdf1d4ba1e00fcab93af91fe4f4f40250d.tar.gz
sssd-2f4e8fbdf1d4ba1e00fcab93af91fe4f4f40250d.tar.bz2
sssd-2f4e8fbdf1d4ba1e00fcab93af91fe4f4f40250d.zip
Validate keytab at startup
In addition to validating the keytab everytime a TGT is requested, we also validate the keytab on back end startup to give early warning that the keytab is not usable. Fixes: #556
-rw-r--r--src/providers/ldap/ldap_child.c51
-rw-r--r--src/providers/ldap/sdap_child_helpers.c16
-rw-r--r--src/util/sss_krb5.c153
-rw-r--r--src/util/sss_krb5.h9
4 files changed, 181 insertions, 48 deletions
diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c
index 17c26855..f51040a7 100644
--- a/src/providers/ldap/ldap_child.c
+++ b/src/providers/ldap/ldap_child.c
@@ -143,10 +143,6 @@ static int ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
krb5_error_code krberr;
krb5_timestamp kdc_time_offset;
int kdc_time_offset_usec;
- krb5_kt_cursor cursor;
- krb5_keytab_entry entry;
- char *principal;
- bool found;
int ret;
krberr = krb5_init_context(&context);
@@ -227,50 +223,9 @@ static int ldap_child_get_tgt_sync(TALLOC_CTX *memctx,
}
/* Verify the keytab */
- krberr = krb5_kt_start_seq_get(context, keytab, &cursor);
- if (krberr) {
- DEBUG(0, ("Cannot read keytab [%s].\n", keytab_name));
-
- sss_log(SSS_LOG_ERR, "Error reading keytab file [%s]: [%d][%s]. "
- "Unable to create GSSAPI-encrypted LDAP connection.",
- keytab_name, krberr,
- sss_krb5_get_error_message(context, krberr));
-
- ret = EFAULT;
- goto done;
- }
-
- found = false;
- while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0){
- krb5_unparse_name(context, entry.principal, &principal);
- if (strcmp(full_princ, principal) == 0) {
- found = true;
- }
- free(principal);
- krb5_free_keytab_entry_contents(context, &entry);
-
- if (found) {
- break;
- }
- }
- krberr = krb5_kt_end_seq_get(context, keytab, &cursor);
- if (krberr) {
- DEBUG(0, ("Could not close keytab.\n"));
- sss_log(SSS_LOG_ERR, "Could not close keytab file [%s].",
- keytab_name);
- ret = EFAULT;
- goto done;
- }
-
- if (!found) {
- DEBUG(0, ("Principal [%s] not found in keytab [%s]\n",
- full_princ, keytab_name));
- sss_log(SSS_LOG_ERR, "Error processing keytab file [%s]: "
- "Principal [%s] was not found. "
- "Unable to create GSSAPI-encrypted LDAP connection.",
- keytab_name, full_princ);
-
- ret = EFAULT;
+ ret = sss_krb5_verify_keytab_ex(full_princ, keytab_name, context, keytab);
+ if (ret) {
+ DEBUG(2, ("Unable to verify principal is present in the keytab\n"));
goto done;
}
diff --git a/src/providers/ldap/sdap_child_helpers.c b/src/providers/ldap/sdap_child_helpers.c
index 58b757ef..1b122485 100644
--- a/src/providers/ldap/sdap_child_helpers.c
+++ b/src/providers/ldap/sdap_child_helpers.c
@@ -29,6 +29,7 @@
#include <fcntl.h>
#include "util/util.h"
+#include "util/sss_krb5.h"
#include "providers/ldap/ldap_common.h"
#include "providers/ldap/sdap_async_private.h"
#include "providers/child_common.h"
@@ -455,6 +456,21 @@ int setup_child(struct sdap_id_ctx *ctx)
return EOK;
}
+ if (mech && (strcasecmp(mech, "GSSAPI") == 0)) {
+ ret = sss_krb5_verify_keytab(dp_opt_get_string(ctx->opts->basic,
+ SDAP_SASL_AUTHID),
+ dp_opt_get_string(ctx->opts->basic,
+ SDAP_KRB5_REALM),
+ dp_opt_get_string(ctx->opts->basic,
+ SDAP_KRB5_KEYTAB));
+
+ if (ret != EOK) {
+ DEBUG(0, ("Could not verify keytab\n"))
+ return ret;
+ }
+
+ }
+
if (debug_to_file != 0 && ldap_child_debug_fd == -1) {
ret = open_debug_file_ex("ldap_child", &debug_filep);
if (ret != EOK) {
diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c
index 0bc25df1..bbb62f11 100644
--- a/src/util/sss_krb5.c
+++ b/src/util/sss_krb5.c
@@ -26,7 +26,160 @@
#include "util/util.h"
#include "util/sss_krb5.h"
+int sss_krb5_verify_keytab(const char *principal,
+ const char *realm_str,
+ const char *keytab_name)
+{
+ krb5_context context = NULL;
+ krb5_keytab keytab = NULL;
+ krb5_error_code krberr;
+ int ret;
+ char *full_princ = NULL;
+ char *realm_name = NULL;
+ char *default_realm = NULL;
+ TALLOC_CTX *tmp_ctx;
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ return ENOMEM;
+ }
+
+ krberr = krb5_init_context(&context);
+ if (krberr) {
+ DEBUG(2, ("Failed to init kerberos context\n"));
+ ret = EFAULT;
+ goto done;
+ }
+
+ if (keytab_name) {
+ krberr = krb5_kt_resolve(context, keytab_name, &keytab);
+ } else {
+ krberr = krb5_kt_default(context, &keytab);
+ }
+
+ if (krberr) {
+ DEBUG(0, ("Failed to read keytab file: %s\n",
+ sss_krb5_get_error_message(context, krberr)));
+ ret = EFAULT;
+ goto done;
+ }
+
+ if (!realm_str) {
+ krberr = krb5_get_default_realm(context, &default_realm);
+ if (krberr) {
+ DEBUG(2, ("Failed to get default realm name: %s\n",
+ sss_krb5_get_error_message(context, krberr)));
+ ret = EFAULT;
+ goto done;
+ }
+
+ realm_name = talloc_strdup(tmp_ctx, default_realm);
+ krb5_free_default_realm(context, default_realm);
+ if (!realm_name) {
+ ret = ENOMEM;
+ goto done;
+ }
+ } else {
+ realm_name = talloc_strdup(tmp_ctx, realm_str);
+ if (!realm_name) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+ if (principal) {
+ if (!strchr(principal, '@')) {
+ full_princ = talloc_asprintf(tmp_ctx, "%s@%s",
+ principal, realm_name);
+ } else {
+ full_princ = talloc_strdup(tmp_ctx, principal);
+ }
+ } else {
+ char hostname[512];
+
+ ret = gethostname(hostname, 511);
+ if (ret == -1) {
+ ret = errno;
+ goto done;
+ }
+ hostname[511] = '\0';
+
+ full_princ = talloc_asprintf(tmp_ctx, "host/%s@%s",
+ hostname, realm_name);
+ }
+ if (!full_princ) {
+ ret = ENOMEM;
+ goto done;
+ }
+ DEBUG(4, ("Principal name is: [%s]\n", full_princ));
+
+ ret = sss_krb5_verify_keytab_ex(full_princ, keytab_name, context, keytab);
+ if (ret) goto done;
+
+ ret = EOK;
+done:
+ if (keytab) krb5_kt_close(context, keytab);
+ if (context) krb5_free_context(context);
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+int sss_krb5_verify_keytab_ex(const char *principal, const char *keytab_name,
+ krb5_context context, krb5_keytab keytab)
+{
+ bool found;
+ char *kt_principal;
+ krb5_error_code krberr;
+ krb5_kt_cursor cursor;
+ krb5_keytab_entry entry;
+
+ krberr = krb5_kt_start_seq_get(context, keytab, &cursor);
+ if (krberr) {
+ DEBUG(0, ("Cannot read keytab [%s].\n", keytab_name));
+
+ sss_log(SSS_LOG_ERR, "Error reading keytab file [%s]: [%d][%s]. "
+ "Unable to create GSSAPI-encrypted LDAP connection.",
+ keytab_name, krberr,
+ sss_krb5_get_error_message(context, krberr));
+
+ return EIO;
+ }
+
+ found = false;
+ while((krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0){
+ krb5_unparse_name(context, entry.principal, &kt_principal);
+ if (strcmp(principal, kt_principal) == 0) {
+ found = true;
+ }
+ free(kt_principal);
+ krb5_free_keytab_entry_contents(context, &entry);
+
+ if (found) {
+ break;
+ }
+ }
+
+ krberr = krb5_kt_end_seq_get(context, keytab, &cursor);
+ if (krberr) {
+ DEBUG(0, ("Could not close keytab.\n"));
+ sss_log(SSS_LOG_ERR, "Could not close keytab file [%s].",
+ keytab_name);
+ return EIO;
+ }
+
+ if (!found) {
+ DEBUG(0, ("Principal [%s] not found in keytab [%s]\n",
+ principal, keytab_name ? keytab_name : "default"));
+ sss_log(SSS_LOG_ERR, "Error processing keytab file [%s]: "
+ "Principal [%s] was not found. "
+ "Unable to create GSSAPI-encrypted LDAP connection.",
+ keytab_name, principal);
+
+ return EFAULT;
+ }
+
+ return EOK;
+}
const char *KRB5_CALLCONV sss_krb5_get_error_message(krb5_context ctx,
krb5_error_code ec)
diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h
index 60994e12..bc7a4f8a 100644
--- a/src/util/sss_krb5.h
+++ b/src/util/sss_krb5.h
@@ -24,6 +24,7 @@
#include "config.h"
#include <stdbool.h>
+#include <talloc.h>
#ifdef HAVE_KRB5_KRB5_H
#include <krb5/krb5.h>
@@ -47,4 +48,12 @@ void KRB5_CALLCONV sss_krb5_free_unparsed_name(krb5_context context, char *name)
krb5_error_code check_for_valid_tgt(const char *ccname, const char *realm,
const char *client_princ_str, bool *result);
+
+int sss_krb5_verify_keytab(const char *principal,
+ const char *realm_str,
+ const char *keytab_name);
+
+int sss_krb5_verify_keytab_ex(const char *principal, const char *keytab_name,
+ krb5_context context, krb5_keytab keytab);
+
#endif /* __SSS_KRB5_H__ */