summaryrefslogtreecommitdiff
path: root/source3/libads/kerberos_verify.c
diff options
context:
space:
mode:
authorDan Sledz <dsledz@isilon.com>2009-01-15 17:02:41 -0800
committerSteven Danneman <steven.danneman@isilon.com>2009-02-01 20:23:31 -0800
commitd96248a9b46559552f53b0ecd3861387ea7ff050 (patch)
treee7d5f3d00f0831d1cb2c4315cd2fa7e1de6abaf6 /source3/libads/kerberos_verify.c
parentd75b3913c9e03ff97336aa7a6e1cbac2eb03f230 (diff)
downloadsamba-d96248a9b46559552f53b0ecd3861387ea7ff050.tar.gz
samba-d96248a9b46559552f53b0ecd3861387ea7ff050.tar.bz2
samba-d96248a9b46559552f53b0ecd3861387ea7ff050.zip
Add two new parameters to control how we verify kerberos tickets. Removes lp_use_kerberos_keytab parameter.
The first is "kerberos method" and replaces the "use kerberos keytab" with an enum. Valid options are: secrets only - use only the secrets for ticket verification (default) system keytab - use only the system keytab for ticket verification dedicated keytab - use a dedicated keytab for ticket verification. secrets and keytab - use the secrets.tdb first, then the system keytab For existing installs: "use kerberos keytab = yes" corresponds to secrets and keytab "use kerberos keytab = no" corresponds to secrets only The major difference between "system keytab" and "dedicated keytab" is that the latter method relies on kerberos to find the correct keytab entry instead of filtering based on expected principals. The second parameter is "dedicated keytab file", which is the keytab to use when in "dedicated keytab" mode. This keytab is only used in ads_verify_ticket.
Diffstat (limited to 'source3/libads/kerberos_verify.c')
-rw-r--r--source3/libads/kerberos_verify.c129
1 files changed, 112 insertions, 17 deletions
diff --git a/source3/libads/kerberos_verify.c b/source3/libads/kerberos_verify.c
index de3fdeb9de..4483d2be58 100644
--- a/source3/libads/kerberos_verify.c
+++ b/source3/libads/kerberos_verify.c
@@ -31,6 +31,86 @@
const krb5_data *krb5_princ_component(krb5_context, krb5_principal, int );
#endif
+static bool ads_dedicated_keytab_verify_ticket(krb5_context context,
+ krb5_auth_context auth_context,
+ const DATA_BLOB *ticket,
+ krb5_ticket **pp_tkt,
+ krb5_keyblock **keyblock,
+ krb5_error_code *perr)
+{
+ krb5_error_code ret = 0;
+ bool auth_ok = false;
+ krb5_keytab keytab = NULL;
+ krb5_keytab_entry kt_entry;
+ krb5_ticket *dec_ticket = NULL;
+
+ krb5_data packet;
+
+ *pp_tkt = NULL;
+ *keyblock = NULL;
+ *perr = 0;
+
+ ZERO_STRUCT(kt_entry);
+
+ ret = smb_krb5_open_keytab(context, lp_dedicated_keytab_file(), true,
+ &keytab);
+ if (ret) {
+ DEBUG(1, ("smb_krb5_open_keytab failed (%s)\n",
+ error_message(ret)));
+ goto out;
+ }
+
+ packet.length = ticket->length;
+ packet.data = (char *)ticket->data;
+ *pp_tkt = NULL;
+
+ ret = krb5_rd_req(context, &auth_context, &packet, NULL, keytab,
+ NULL, &dec_ticket);
+ if (ret) {
+ DEBUG(0, ("krb5_rd_req failed (%s)\n", error_message(ret)));
+ goto out;
+ }
+
+ /* Get the key for checking the pac signature */
+ ret = krb5_kt_get_entry(context, keytab, dec_ticket->server,
+ dec_ticket->enc_part.kvno, dec_ticket->enc_part.enctype,
+ &kt_entry);
+ if (ret) {
+ DEBUG(0, ("krb5_kt_get_entry failed (%s)\n",
+ error_message(ret)));
+ goto out;
+ }
+
+#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */
+ ret = krb5_copy_keyblock(context, &kt_entry.keyblock, keyblock);
+#elif defined(HAVE_KRB5_KEYTAB_ENTRY_KEY) /* MIT */
+ ret = krb5_copy_keyblock(context, &kt_entry.key, keyblock);
+#else
+#error UNKNOWN_KRB5_KEYTAB_ENTRY_FORMAT
+#endif
+ smb_krb5_kt_free_entry(context, &kt_entry);
+
+ if (ret) {
+ DEBUG(0, ("failed to copy key: %s\n",
+ error_message(ret)));
+ goto out;
+ }
+
+ auth_ok = true;
+ *pp_tkt = dec_ticket;
+ dec_ticket = NULL;
+
+ out:
+ if (dec_ticket)
+ krb5_free_ticket(context, dec_ticket);
+
+ if (keytab)
+ krb5_kt_close(context, keytab);
+
+ *perr = ret;
+ return auth_ok;
+}
+
/**********************************************************************************
Try to verify a ticket using the system keytab... the system keytab has kvno -1 entries, so
it's more like what microsoft does... see comment in utils/net_ads.c in the
@@ -437,22 +517,38 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
}
}
- /* Try secrets.tdb first and fallback to the krb5.keytab if
- necessary */
-
- auth_ok = ads_secrets_verify_ticket(context, auth_context, host_princ,
- ticket, &tkt, &keyblock, &ret);
-
- if (!auth_ok &&
- (ret == KRB5KRB_AP_ERR_TKT_NYV ||
- ret == KRB5KRB_AP_ERR_TKT_EXPIRED ||
- ret == KRB5KRB_AP_ERR_SKEW)) {
- goto auth_failed;
- }
-
- if (!auth_ok && lp_use_kerberos_keytab()) {
- auth_ok = ads_keytab_verify_ticket(context, auth_context,
- ticket, &tkt, &keyblock, &ret);
+ switch (lp_kerberos_method()) {
+ default:
+ case KERBEROS_VERIFY_SECRETS:
+ auth_ok = ads_secrets_verify_ticket(context, auth_context,
+ host_princ, ticket, &tkt, &keyblock, &ret);
+ break;
+ case KERBEROS_VERIFY_SYSTEM_KEYTAB:
+ auth_ok = ads_keytab_verify_ticket(context, auth_context,
+ ticket, &tkt, &keyblock, &ret);
+ break;
+ case KERBEROS_VERIFY_DEDICATED_KEYTAB:
+ auth_ok = ads_dedicated_keytab_verify_ticket(context,
+ auth_context, ticket, &tkt, &keyblock, &ret);
+ break;
+ case KERBEROS_VERIFY_SECRETS_AND_KEYTAB:
+ /* First try secrets.tdb and fallback to the krb5.keytab if
+ necessary. This is the pre 3.4 behavior when
+ "use kerberos keytab" was true.*/
+ auth_ok = ads_secrets_verify_ticket(context, auth_context,
+ host_princ, ticket, &tkt, &keyblock, &ret);
+
+ if (!auth_ok) {
+ /* Only fallback if we failed to decrypt the ticket */
+ if (ret != KRB5KRB_AP_ERR_TKT_NYV &&
+ ret != KRB5KRB_AP_ERR_TKT_EXPIRED &&
+ ret != KRB5KRB_AP_ERR_SKEW) {
+ auth_ok = ads_keytab_verify_ticket(context,
+ auth_context, ticket, &tkt, &keyblock,
+ &ret);
+ }
+ }
+ break;
}
if ( use_replay_cache ) {
@@ -465,7 +561,6 @@ NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
#endif
}
- auth_failed:
if (!auth_ok) {
DEBUG(3,("ads_verify_ticket: krb5_rd_req with auth failed (%s)\n",
error_message(ret)));