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__ */  | 
