diff options
author | Jakub Hrozek <jhrozek@redhat.com> | 2010-07-20 18:35:50 +0200 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2010-08-03 13:50:28 -0400 |
commit | 2f4e8fbdf1d4ba1e00fcab93af91fe4f4f40250d (patch) | |
tree | 555aa8943fe4bf30d52d2dd64bde1fe5692b0b09 | |
parent | 13d90c2ae8413317947d392c89fffca10ec83587 (diff) | |
download | sssd-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.c | 51 | ||||
-rw-r--r-- | src/providers/ldap/sdap_child_helpers.c | 16 | ||||
-rw-r--r-- | src/util/sss_krb5.c | 153 | ||||
-rw-r--r-- | src/util/sss_krb5.h | 9 |
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__ */ |