summaryrefslogtreecommitdiff
path: root/source3/libads/kerberos_verify.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libads/kerberos_verify.c')
-rw-r--r--source3/libads/kerberos_verify.c165
1 files changed, 155 insertions, 10 deletions
diff --git a/source3/libads/kerberos_verify.c b/source3/libads/kerberos_verify.c
index 48b61cd1f2..4ae89aa01f 100644
--- a/source3/libads/kerberos_verify.c
+++ b/source3/libads/kerberos_verify.c
@@ -4,6 +4,8 @@
Copyright (C) Andrew Tridgell 2001
Copyright (C) Remus Koos 2001
Copyright (C) Luke Howard 2003
+ Copyright (C) Guenther Deschner 2003
+ Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -24,11 +26,132 @@
#ifdef HAVE_KRB5
+static void free_keytab(krb5_context context, krb5_keytab keytab)
+{
+ int ret=0;
+
+ if (keytab)
+ ret = krb5_kt_close(context, keytab);
+ if (ret) {
+ DEBUG(3, ("krb5_kt_close failed (%s)\n",
+ error_message(ret)));
+ }
+}
+
+#ifdef HAVE_MEMORY_KEYTAB
+static krb5_error_code create_keytab(krb5_context context,
+ krb5_principal host_princ,
+ char *host_princ_s,
+ krb5_data password,
+ krb5_enctype *enctypes,
+ krb5_keytab *keytab,
+ char *keytab_name)
+{
+ krb5_keytab_entry entry;
+ krb5_kvno kvno = 1;
+ krb5_error_code ret;
+ krb5_keyblock *key;
+ int i;
+
+ DEBUG(10,("creating keytab: %s\n", keytab_name));
+ ret = krb5_kt_resolve(context, keytab_name, keytab);
+ if (ret)
+ return ret;
+
+ if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) {
+ return ENOMEM;
+ }
+
+ /* add keytab entries for all encryption types */
+ for ( i=0; enctypes[i]; i++ ) {
+
+ if (create_kerberos_key_from_string(context, host_princ, &password, key, enctypes[i])) {
+ continue;
+ }
+
+ entry.principal = host_princ;
+ entry.vno = kvno;
+ /* this will have to be detected in configure...heimdal
+ calls it keyblock, MIT calls it key, but it does not
+ matter we are creating keytabs with MIT */
+ entry.keyblock = *key;
+
+ DEBUG(10,("adding keytab-entry for (%s) with encryption type (%d)\n",
+ host_princ_s, enctypes[i]));
+ ret = krb5_kt_add_entry(context, *keytab, &entry);
+ if (ret) {
+ DEBUG(1,("adding entry to keytab failed (%s)\n",
+ error_message(ret)));
+ free_keytab(context, *keytab);
+ return ret;
+ }
+ }
+ krb5_free_keyblock(context, key);
+
+ return 0;
+}
+#endif
+
+static BOOL setup_keytab(krb5_context context,
+ krb5_principal host_princ,
+ char *host_princ_s,
+ krb5_data password,
+ krb5_enctype *enctypes,
+ krb5_keytab *keytab)
+{
+ char *keytab_name = NULL;
+ krb5_error_code ret;
+
+ /* check if we have to setup a keytab - not currently enabled
+ I've put this in so that the else block below functions
+ the same way that it will when this code is turned on */
+ if (0 /* will later be *lp_keytab() */) {
+
+ /* use a file-keytab */
+ asprintf(&keytab_name, "%s:%s",
+ ""
+ /* KRB5_KT_FILE_PREFIX, "FILE" or
+ "WRFILE" depending on HEeimdal or MIT */,
+ "" /* will later be lp_keytab() */);
+
+ DEBUG(10,("will use filebased keytab: %s\n", keytab_name));
+ ret = krb5_kt_resolve(context, keytab_name, keytab);
+ if (ret) {
+ DEBUG(3,("cannot resolve keytab name %s (%s)\n",
+ keytab_name,
+ error_message(ret)));
+ SAFE_FREE(keytab_name);
+ return False;
+ }
+
+ }
+
+#if defined(HAVE_MEMORY_KEYTAB)
+ else {
+
+ /* setup a in-memory-keytab */
+ asprintf(&keytab_name, "MEMORY:");
+
+ ret = create_keytab(context, host_princ, host_princ_s, password, enctypes,
+ keytab, keytab_name);
+ if (ret) {
+ DEBUG(3,("unable to create MEMORY: keytab (%s)\n",
+ error_message(ret)));
+ SAFE_FREE(keytab_name);
+ return False;
+ }
+ }
+#endif
+ SAFE_FREE(keytab_name);
+ return True;
+}
+
+
/*
verify an incoming ticket and parse out the principal name and
authorization_data if available
*/
-NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket,
+NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
char **principal, DATA_BLOB *auth_data,
DATA_BLOB *ap_rep,
uint8 session_key[16])
@@ -79,7 +202,7 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket,
return NT_STATUS_LOGON_FAILURE;
}
- ret = krb5_set_default_realm(context, ads->auth.realm);
+ ret = krb5_set_default_realm(context, realm);
if (ret) {
DEBUG(1,("ads_verify_ticket: krb5_set_default_realm failed (%s)\n", error_message(ret)));
sret = NT_STATUS_LOGON_FAILURE;
@@ -128,11 +251,6 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket,
/* CIFS doesn't use addresses in tickets. This would breat NAT. JRA */
- if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) {
- sret = NT_STATUS_NO_MEMORY;
- goto out;
- }
-
if ((ret = get_kerberos_allowed_etypes(context, &enctypes))) {
DEBUG(1,("ads_verify_ticket: krb5_get_permitted_enctypes failed (%s)\n",
error_message(ret)));
@@ -149,22 +267,40 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket,
goto out;
}
+ if (!setup_keytab(context, host_princ, host_princ_s, password,
+ enctypes, &keytab)) {
+ DEBUG(3,("ads_verify_ticket: unable to setup keytab\n"));
+ sret = NT_STATUS_LOGON_FAILURE;
+ goto out;
+ }
+
/* We need to setup a auth context with each possible encoding type in turn. */
for (i=0;enctypes[i];i++) {
+ if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) {
+ sret = NT_STATUS_NO_MEMORY;
+ goto out;
+ }
+
if (create_kerberos_key_from_string(context, host_princ, &password, key, enctypes[i])) {
continue;
}
krb5_auth_con_setuseruserkey(context, auth_context, key);
+ krb5_free_keyblock(context, key);
+
packet.length = ticket->length;
packet.data = (krb5_pointer)ticket->data;
if (!(ret = krb5_rd_req(context, &auth_context, &packet,
- NULL, keytab, NULL, &tkt))) {
+#ifdef HAVE_MEMORY_KEYTAB
+ host_princ,
+#else
+ NULL,
+#endif
+ keytab, NULL, &tkt))) {
DEBUG(10,("ads_verify_ticket: enc type [%u] decrypted message !\n",
(unsigned int)enctypes[i] ));
- free_kerberos_etypes(context, enctypes);
auth_ok = True;
break;
}
@@ -217,8 +353,13 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket,
file_save("/tmp/authdata.dat",
tkt->enc_part2->authorization_data[0]->contents,
tkt->enc_part2->authorization_data[0]->length);
+ }
#endif
+
+ /* get rid of all resources associated with the keytab */
+ if (keytab) free_keytab(context, keytab);
+
if ((ret = krb5_unparse_name(context, get_principal_from_tkt(tkt),
principal))) {
DEBUG(3,("ads_verify_ticket: krb5_unparse_name failed (%s)\n",
@@ -237,8 +378,12 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket,
if (!NT_STATUS_IS_OK(sret))
data_blob_free(ap_rep);
- SAFE_FREE(host_princ_s);
+ krb5_free_principal(context, host_princ);
+ if (tkt != NULL)
+ krb5_free_ticket(context, tkt);
+ free_kerberos_etypes(context, enctypes);
SAFE_FREE(password_s);
+ SAFE_FREE(host_princ_s);
if (auth_context)
krb5_auth_con_free(context, auth_context);