--- source/configure.in	22 Feb 2003 12:19:18 -0000	1.409
+++ source/configure.in	24 Feb 2003 06:04:25 -0000
@@ -627,6 +627,15 @@
 fi
 
 ############################################
+# support for using Kerberos keytab instead of secrets database
+
+AC_ARG_ENABLE(keytab, 
+[  --enable-keytab         Turn on support for Kerberos keytabs in lieu of secrets DB (default=no)],
+    [if eval "test x$enable_keytab = xyes"; then
+	AC_DEFINE(USE_KEYTAB,1,[Use Kerberos keytab])
+    fi])
+
+############################################
 # we need dlopen/dlclose/dlsym/dlerror for PAM, the password database plugins and the plugin loading code
 AC_SEARCH_LIBS(dlopen, [dl])
 # dlopen/dlclose/dlsym/dlerror will be checked again later and defines will be set then
--- source/passdb/secrets.c	1 Feb 2003 04:39:15 -0000	1.54
+++ source/passdb/secrets.c	24 Feb 2003 06:04:26 -0000
@@ -221,6 +221,72 @@
 	return True;
 }
 
+#ifdef USE_KEYTAB
+/************************************************************************
+ Read local secret from the keytab
+************************************************************************/
+
+static BOOL secrets_fetch_keytab_password(uint8 ret_pwd[16], time_t *pass_last_set_time)
+{
+	char spn[MAXHOSTNAMELEN + 2], *p;
+	krb5_context context;
+	krb5_error_code ret;
+	krb5_principal princ;
+	krb5_keyblock *key;
+
+	ret = krb5_init_context(&context);
+	if (ret) {
+		DEBUG(1, ("secrets_fetch_keytab_password: failed to initialize Kerberos context\n"));
+		return False;
+	}
+
+	spn[sizeof(spn) - 1] = '\0';
+	if (gethostname(spn, sizeof(spn) - 2) < 0) {
+		DEBUG(1, ("secrets_fetch_keytab_password: could not determine local hostname\n"));
+		krb5_free_context(context);
+		return False;
+	}
+
+	for (p = spn; *p && *p != '.'; p++)
+		*p = toupper(*p);
+	*p++ = '$';
+	*p = '\0';
+
+	ret = krb5_parse_name(context, spn, &princ);
+	if (ret) {
+		DEBUG(1, ("secrets_fetch_keytab_password: failed to parse name %s\n", spn));
+		krb5_free_context(context);
+		return False;
+	}
+
+#ifdef ENCTYPE_ARCFOUR_HMAC
+	ret = krb5_kt_read_service_key(context, NULL, princ, 0, ENCTYPE_ARCFOUR_HMAC, &key);
+#elif defined(HAVE_ENCTYPE_ARCFOUR_HMAC_MD5)
+	ret = krb5_kt_read_service_key(context, NULL, princ, 0, ENCTYPE_ARCFOUR_HMAC_MD5, &key);
+#else
+#error ENCTYPE_ARCFOUR_HMAC or ENCTYPE_ARCFOUR_HMAC_MD5 required for keytab secret storage
+#endif 
+	if (ret) {
+		DEBUG(1, ("secrets_fetch_keytab_password: failed to read secret for %s\n", spn));
+		krb5_free_context(context);
+		return False;
+	}
+	if (key->keyvalue.length != 16) {
+		DEBUG(1, ("secrets_fetch_keytab_password: key is incorrect length\n"));
+		krb5_free_context(context);
+		return False;
+	}
+
+	memcpy(ret_pwd, key->keyvalue.data, key->keyvalue.length);
+	time(pass_last_set_time); /* XXX */
+
+	krb5_free_keyblock(context, key);
+	krb5_free_context(context);
+
+	return True;
+}
+#endif /* USE_KEYTAB */
+
 /************************************************************************
  Routine to get the trust account password for a domain.
  The user of this function must have locked the trust password file using
@@ -243,6 +309,12 @@
 		pass_last_set_time = 0;
 		return True;
 	}
+
+#ifdef USE_KEYTAB
+	if (is_myworkgroup(domain)) {
+		return secrets_fetch_keytab_password(ret_pwd, pass_last_set_time);
+	}
+#endif /* USE_KEYTAB */
 
 	if (!(pass = secrets_fetch(trust_keystr(domain), &size))) {
 		DEBUG(5, ("secrets_fetch failed!\n"));
 
--- source/libsmb/clikrb5.c	2003-07-02 00:32:55.000000000 +0200
+++ source/libsmb/clikrb5.c	2003-07-02 00:37:22.000000000 +0200
@@ -316,11 +316,13 @@
 	krb5_enctype enc_types[] = {
 #ifdef ENCTYPE_ARCFOUR_HMAC
 		ENCTYPE_ARCFOUR_HMAC,
+#elif defined(HAVE_ENCTYPE_ARCFOUR_HMAC_MD5)
+		ENCTYPE_ARCFOUR_HMAC_MD5,
 #endif 
 		ENCTYPE_DES_CBC_MD5, 
 		ENCTYPE_DES_CBC_CRC, 
 		ENCTYPE_NULL};
-	
+	
 	retval = krb5_init_context(&context);
 	if (retval) {
 		DEBUG(1,("krb5_init_context failed (%s)\n", 
@@ -367,24 +369,26 @@
 
  BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16])
  {
-#ifdef ENCTYPE_ARCFOUR_HMAC
 	krb5_keyblock *skey;
-#endif
 	BOOL ret = False;
 
 	memset(session_key, 0, 16);
 
-#ifdef ENCTYPE_ARCFOUR_HMAC
+#if defined(ENCTYPE_ARCFOUR_HMAC) || defined(HAVE_ENCTYPE_ARCFOUR_HMAC_MD5)
 	if (krb5_auth_con_getremotesubkey(context, auth_context, &skey) == 0 && skey != NULL) {
 		if (KRB5_KEY_TYPE(skey) ==
+# ifdef ENCTYPE_ARCFOUR_HMAC
 		    ENCTYPE_ARCFOUR_HMAC
+# else
+		    ENCTYPE_ARCFOUR_HMAC_MD5
+# endif /* ENCTYPE_ARCFOUR_HMAC */
 		    && KRB5_KEY_LENGTH(skey) == 16) {
 			memcpy(session_key, KRB5_KEY_DATA(skey), KRB5_KEY_LENGTH(skey));
 			ret = True;
 		}
 		krb5_free_keyblock(context, skey);
 	}
-#endif /* ENCTYPE_ARCFOUR_HMAC */
+#endif /* ENCTYPE_ARCFOUR_HMAC || HAVE_ENCTYPE_ARCFOUR_HMAC_MD5 */
 
 	return ret;
  }
@@ -395,5 +399,12 @@
 	 DEBUG(0,("NO KERBEROS SUPPORT\n"));
 	 return data_blob(NULL, 0);
  }
+BOOL krb5_get_smb_session_key(krb5_context context, krb5_auth_context ac, uint8 session_key[16])
+ {
+	DEBUG(0,("NO KERBEROS SUPPORT\n"));
+	memset(session_key, 0, 16);
+	return False;
+ }
+ //#endif
 
 #endif
--- source/libads/kerberos_verify.c	2003-06-28 23:40:55.000000000 +0200
+++ source/libads/kerberos_verify.c	2003-07-02 00:50:13.000000000 +0200
@@ -38,7 +38,9 @@
 	krb5_keytab keytab = NULL;
 	krb5_data packet;
 	krb5_ticket *tkt = NULL;
-	int ret, i;
+	int ret;
+#ifndef USE_KEYTAB
+	int i;
 	krb5_keyblock * key;
 	krb5_principal host_princ;
 	char *host_princ_s;
@@ -46,8 +48,10 @@
 	char *password_s;
 	krb5_data password;
 	krb5_enctype *enctypes = NULL;
+#endif /* USE_KEYTAB */
 	BOOL auth_ok = False;
 
+#ifndef USE_KEYTAB
 	if (!secrets_init()) {
 		DEBUG(1,("secrets_init failed\n"));
 		return NT_STATUS_LOGON_FAILURE;
@@ -61,6 +65,7 @@
 
 	password.data = password_s;
 	password.length = strlen(password_s);
+#endif /* USE_KEYTAB */
 
 	ret = krb5_init_context(&context);
 	if (ret) {
@@ -82,7 +87,16 @@
 		DEBUG(1,("krb5_auth_con_init failed (%s)\n", error_message(ret)));
 		return NT_STATUS_LOGON_FAILURE;
 	}
+#ifdef USE_KEYTAB
+	packet.length = ticket->length;
+	packet.data = (krb5_pointer)ticket->data;
 
+	if (!(ret = krb5_rd_req(context, &auth_context, &packet, 
+				NULL, keytab, NULL, &tkt))) {
+		auth_ok = True;
+	}
+
+#else
 	fstrcpy(myname, global_myname());
 	strlower(myname);
 	asprintf(&host_princ_s, "HOST/%s@%s", myname, lp_realm());
@@ -121,6 +135,9 @@
 		}
 	}
 
+	SAFE_FREE(key);
+#endif /* USE_KEYTAB */
+
 	if (!auth_ok) {
 		DEBUG(3,("krb5_rd_req with auth failed (%s)\n", 
 			 error_message(ret)));
--- source/Makefile.in	2003-07-01 23:35:49.000000000 +0200
+++ source/Makefile.in	2003-07-02 01:20:09.000000000 +0200
@@ -806,7 +806,7 @@
 
 bin/pdbedit@EXEEXT@: $(PDBEDIT_OBJ) @BUILD_POPT@ bin/.dummy
 	@echo Linking $@
-	@$(CC) $(FLAGS) -o $@ $(IDMAP_LIBS) $(PDBEDIT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(PASSDBLIBS)
+	@$(CC) $(FLAGS) -o $@ $(IDMAP_LIBS) $(PDBEDIT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(PASSDBLIBS) $(KRB5LIBS)
 
 bin/samtest@EXEEXT@: $(SAMTEST_OBJ) @BUILD_POPT@ bin/.dummy
 	@echo Linking $@
@@ -1062,7 +1062,7 @@
 
 bin/wbinfo@EXEEXT@: $(WBINFO_OBJ) @BUILD_POPT@ bin/.dummy
 	@echo Linking $@
-	@$(LINK) -o $@ $(WBINFO_OBJ) $(LIBS) @POPTLIBS@
+	@$(LINK) -o $@ $(WBINFO_OBJ) $(LIBS) @POPTLIBS@ $(KRB5LIBS)
 
 bin/ntlm_auth@EXEEXT@: $(NTLM_AUTH_OBJ) $(PARAM_OBJ) $(LIB_OBJ) \
 		$(UBIQX_OBJ) @BUILD_POPT@ bin/.dummy
