summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim McDonough <jmcd@samba.org>2003-09-03 00:45:15 +0000
committerJim McDonough <jmcd@samba.org>2003-09-03 00:45:15 +0000
commitd517c1d613d7cace619878ca9853b154aa71dec3 (patch)
treedd54ba48e9fd594dd39943745caa71d94c192eb0
parenta7e8e39b91c661ac0058929a7e46c9d4da2763f2 (diff)
downloadsamba-d517c1d613d7cace619878ca9853b154aa71dec3.tar.gz
samba-d517c1d613d7cace619878ca9853b154aa71dec3.tar.bz2
samba-d517c1d613d7cace619878ca9853b154aa71dec3.zip
Try to add memory keytab support. It also includes much of the generic
keytab support code, but it won't be enabled until we add that to smb.conf. Adapted from the work of Guenther Deschner (gd@suse.com). Please hammer on this... (This used to be commit a26fa5bee24c73cd835f59bb18162ab07760d76a)
-rw-r--r--source3/libads/kerberos_verify.c142
1 files changed, 141 insertions, 1 deletions
diff --git a/source3/libads/kerberos_verify.c b/source3/libads/kerberos_verify.c
index 4bd20a3639..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,6 +26,127 @@
#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
@@ -144,6 +267,13 @@ NTSTATUS ads_verify_ticket(const char *realm, 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)))) {
@@ -163,7 +293,12 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
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] ));
auth_ok = True;
@@ -218,8 +353,13 @@ NTSTATUS ads_verify_ticket(const char *realm, 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",