summaryrefslogtreecommitdiffstats
path: root/src/util
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 /src/util
parent13d90c2ae8413317947d392c89fffca10ec83587 (diff)
downloadsssd-2f4e8fbdf1d4ba1e00fcab93af91fe4f4f40250d.tar.gz
sssd-2f4e8fbdf1d4ba1e00fcab93af91fe4f4f40250d.tar.xz
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
Diffstat (limited to 'src/util')
-rw-r--r--src/util/sss_krb5.c153
-rw-r--r--src/util/sss_krb5.h9
2 files changed, 162 insertions, 0 deletions
diff --git a/src/util/sss_krb5.c b/src/util/sss_krb5.c
index 0bc25df17..bbb62f11a 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 60994e123..bc7a4f8a2 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__ */