summaryrefslogtreecommitdiff
path: root/source4/auth
diff options
context:
space:
mode:
authorAndreas Schneider <asn@samba.org>2015-04-17 15:53:41 +0200
committerJeremy Allison <jra@samba.org>2015-07-17 01:38:15 +0200
commit6ba4d2d04e8ea5818c306ed1b3fa3b4b8130b629 (patch)
tree04fce29271901d975bc07a7aa4c536eb20cd9240 /source4/auth
parent398b2877127ac46f4c2ea9a6c4ef3112e1a44f5f (diff)
downloadsamba-6ba4d2d04e8ea5818c306ed1b3fa3b4b8130b629.tar.gz
s4-auth: Add smb_krb5_remove_obsolete_keytab_entries()
Signed-off-by: Andreas Schneider <asn@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
Diffstat (limited to 'source4/auth')
-rw-r--r--source4/auth/kerberos/kerberos_util.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/source4/auth/kerberos/kerberos_util.c b/source4/auth/kerberos/kerberos_util.c
index 9cfeee519b4..b7f5ab0f09f 100644
--- a/source4/auth/kerberos/kerberos_util.c
+++ b/source4/auth/kerberos/kerberos_util.c
@@ -471,3 +471,160 @@ krb5_error_code smb_krb5_get_keytab_container(TALLOC_CTX *mem_ctx,
return 0;
}
+
+/*
+ * Walk the keytab, looking for entries of this principal name,
+ * with KVNO other than current kvno -1.
+ *
+ * These entries are now stale,
+ * we only keep the current and previous entries around.
+ *
+ * Inspired by the code in Samba3 for 'use kerberos keytab'.
+ */
+krb5_error_code smb_krb5_remove_obsolete_keytab_entries(TALLOC_CTX *mem_ctx,
+ krb5_context context,
+ krb5_keytab keytab,
+ uint32_t num_principals,
+ krb5_principal *principals,
+ krb5_kvno kvno,
+ bool *found_previous,
+ const char **error_string)
+{
+ TALLOC_CTX *tmp_ctx;
+ krb5_error_code code;
+ krb5_kt_cursor cursor;
+
+ tmp_ctx = talloc_new(mem_ctx);
+ if (tmp_ctx == NULL) {
+ *error_string = "Cannot allocate tmp_ctx";
+ return ENOMEM;
+ }
+
+ *found_previous = true;
+
+ code = krb5_kt_start_seq_get(context, keytab, &cursor);
+ switch (code) {
+ case 0:
+ break;
+#ifdef HEIM_ERR_OPNOTSUPP
+ case HEIM_ERR_OPNOTSUPP:
+#endif
+ case ENOENT:
+ case KRB5_KT_END:
+ /* no point enumerating if there isn't anything here */
+ code = 0;
+ goto done;
+ default:
+ *error_string = talloc_asprintf(mem_ctx,
+ "failed to open keytab for read of old entries: %s\n",
+ smb_get_krb5_error_message(context, code, mem_ctx));
+ goto done;
+ }
+
+ do {
+ krb5_keytab_entry entry;
+ bool matched = false;
+ uint32_t i;
+
+ code = krb5_kt_next_entry(context, keytab, &entry, &cursor);
+ if (code) {
+ break;
+ }
+
+ for (i = 0; i < num_principals; i++) {
+ krb5_boolean ok;
+
+ ok = smb_krb5_kt_compare(context,
+ &entry,
+ principals[i],
+ 0,
+ 0);
+ if (ok) {
+ matched = true;
+ break;
+ }
+ }
+
+ if (!matched) {
+ /*
+ * Free the entry, it wasn't the one we were looking
+ * for anyway
+ */
+ krb5_kt_free_entry(context, &entry);
+ /* Make sure we do not double free */
+ ZERO_STRUCT(entry);
+ continue;
+ }
+
+ /* Delete it, if it is not kvno - 1 */
+ if (entry.vno != (kvno - 1)) {
+ krb5_error_code rc;
+
+ /* Release the enumeration. We are going to
+ * have to start this from the top again,
+ * because deletes during enumeration may not
+ * always be consistent.
+ *
+ * Also, the enumeration locks a FILE: keytab
+ */
+ krb5_kt_end_seq_get(context, keytab, &cursor);
+
+ code = krb5_kt_remove_entry(context, keytab, &entry);
+ krb5_kt_free_entry(context, &entry);
+
+ /* Make sure we do not double free */
+ ZERO_STRUCT(entry);
+
+ /* Deleted: Restart from the top */
+ rc = krb5_kt_start_seq_get(context, keytab, &cursor);
+ if (rc != 0) {
+ krb5_kt_free_entry(context, &entry);
+
+ /* Make sure we do not double free */
+ ZERO_STRUCT(entry);
+
+ DEBUG(1, ("failed to restart enumeration of keytab: %s\n",
+ smb_get_krb5_error_message(context,
+ code,
+ tmp_ctx)));
+
+ talloc_free(tmp_ctx);
+ return rc;
+ }
+
+ if (code != 0) {
+ break;
+ }
+
+ } else {
+ *found_previous = true;
+ }
+
+ /* Free the entry, we don't need it any more */
+ krb5_kt_free_entry(context, &entry);
+ /* Make sure we do not double free */
+ ZERO_STRUCT(entry);
+ } while (code != 0);
+
+ krb5_kt_end_seq_get(context, keytab, &cursor);
+
+ switch (code) {
+ case 0:
+ break;
+ case ENOENT:
+ case KRB5_KT_END:
+ code = 0;
+ break;
+ default:
+ *error_string = talloc_asprintf(mem_ctx,
+ "failed in deleting old entries for principal: %s\n",
+ smb_get_krb5_error_message(context,
+ code,
+ mem_ctx));
+ }
+
+ code = 0;
+done:
+ talloc_free(tmp_ctx);
+ return code;
+}