heimdal didn't have AP_OPTS_USE_SUBKEY

Luke Howard lukeh at PADL.COM
Sun Feb 2 00:06:26 GMT 2003


Please try the following patch (attached). 

This patch also includes a few other things, so edit as
appropriate:

- support for the DCE NP funnel (available from
  http://www.padl.com/~lukeh/XAD/dce_funnel.tar.gz)
- support for using the keytab instead of the secrets
  database
- support for using RC4 Kerberos session keys as named pipe
  session keys (have not tested with MIT)

You probably won't want any of these things except perhaps for
the latter, but I'm including them to meet our obligations under
the GPL.

cheers,

-- Luke

-------------- next part --------------
Index: Makefile.in
===================================================================
RCS file: /cvsroot/samba/source/Makefile.in,v
retrieving revision 1.606
diff -u -r1.606 Makefile.in
--- Makefile.in	1 Feb 2003 06:26:16 -0000	1.606
+++ Makefile.in	2 Feb 2003 00:00:36 -0000
@@ -228,7 +228,7 @@
 RPC_SPOOLSS_OBJ = rpc_server/srv_spoolss.o rpc_server/srv_spoolss_nt.o 
 
 RPC_PIPE_OBJ = rpc_server/srv_pipe_hnd.o rpc_server/srv_util.o \
-               rpc_server/srv_pipe.o rpc_server/srv_lsa_hnd.o
+               rpc_server/srv_pipe.o rpc_server/srv_lsa_hnd.o rpc_server/srv_dce_funnel.o
 
 # These are like they are to avoid a dependency on GNU MAKE
 @LSA_DYNAMIC_YES at RPC_MODULES1 = bin/librpc_lsarpc. at SHLIBEXT@
Index: configure.in
===================================================================
RCS file: /cvsroot/samba/source/configure.in,v
retrieving revision 1.397
diff -u -r1.397 configure.in
--- configure.in	1 Feb 2003 11:00:39 -0000	1.397
+++ configure.in	2 Feb 2003 00:00:40 -0000
@@ -2165,6 +2165,9 @@
   AC_CHECK_LIB(krb5, krb5_auth_con_setkey, [AC_DEFINE(HAVE_KRB5_AUTH_CON_SETKEY,1,[Whether krb5_auth_con_setkey is available])])
   AC_CHECK_LIB(krb5, krb5_auth_con_setuseruserkey, [AC_DEFINE(HAVE_KRB5_AUTH_CON_SETUSERUSERKEY,1,[Whether krb5_auth_con_setuseruserkey is available])])
   AC_CHECK_LIB(krb5, krb5_locate_kdc, [AC_DEFINE(HAVE_KRB5_LOCATE_KDC,1,[Whether krb5_locate_kdc is available])])
+  AC_CHECK_LIB(krb5, krb5_get_permitted_enctypes, [AC_DEFINE(HAVE_KRB5_GET_PERMITTED_ENCTYPES,1,[Whether krb5_get_permitted_enctypes is available])])
+  AC_CHECK_LIB(krb5, krb5_free_ktypes, [AC_DEFINE(HAVE_KRB5_FREE_KTYPES,1,[Whether krb5_free_ktypes is available])])
+  AC_CHECK_LIB(krb5, krb5_get_default_in_tkt_etypes, [AC_DEFINE(HAVE_KRB5_GET_DEFAULT_IN_TKT_ETYPES,1,[Whether krb5_get_default_in_tkt_etypes is available])])
 
 AC_CACHE_CHECK([for addrtype in krb5_address],samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS,[
 AC_TRY_COMPILE([#include <krb5.h>],
@@ -2198,6 +2201,8 @@
 
   ########################################################
   # now see if we can find the gssapi libs in standard paths
+  AC_CHECK_LIB(gssapi, gss_display_status, [LIBS="$LIBS -lgssapi";
+	AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available])])
   AC_CHECK_LIB(gssapi_krb5, gss_display_status, [LIBS="$LIBS -lgssapi_krb5";
         AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available])])
 
Index: include/includes.h
===================================================================
RCS file: /cvsroot/samba/source/include/includes.h,v
retrieving revision 1.295
diff -u -r1.295 includes.h
--- include/includes.h	30 Jan 2003 20:36:59 -0000	1.295
+++ include/includes.h	2 Feb 2003 00:00:41 -0000
 void get_auth_data_from_tkt(DATA_BLOB *auth_data, krb5_ticket *tkt);
 krb5_const_principal get_principal_from_tkt(krb5_ticket *tkt);
 krb5_error_code krb5_locate_kdc(krb5_context ctx, const krb5_data *realm, struct sockaddr **addr_pp, int *naddrs, int get_masters);
+krb5_error_code krb5_get_permitted_enctypes(krb5_context context, krb5_enctype **enctypes);
+void krb5_free_ktypes(krb5_context context, krb5_enctype *enctypes);
 
 #endif /* HAVE_KRB5 */
 
Index: libads/kerberos_verify.c
===================================================================
RCS file: /cvsroot/samba/source/libads/kerberos_verify.c,v
retrieving revision 1.5
diff -u -r1.5 kerberos_verify.c
--- libads/kerberos_verify.c	11 Jan 2003 03:29:31 -0000	1.5
+++ libads/kerberos_verify.c	2 Feb 2003 00:00:41 -0000
@@ -3,7 +3,7 @@
    kerberos utility library
    Copyright (C) Andrew Tridgell 2001
    Copyright (C) Remus Koos 2001
-   
+   Copyright (C) Luke Howard 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
@@ -29,15 +29,14 @@
   authorization_data if available 
 */
 NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, 
-			   char **principal, DATA_BLOB *auth_data)
+			   char **principal, DATA_BLOB *auth_data,
+			   uint8 session_key[16])
 {
 	krb5_context context;
 	krb5_auth_context auth_context = NULL;
 	krb5_keytab keytab = NULL;
 	krb5_data packet;
 	krb5_ticket *tkt = NULL;
-	krb5_data salt;
-	krb5_encrypt_block eblock;
 	int ret, i;
 	krb5_keyblock * key;
 	krb5_principal host_princ;
@@ -47,7 +46,11 @@
 	krb5_data password;
 	krb5_enctype *enctypes = NULL;
 	BOOL auth_ok = False;
+	krb5_keyblock *skey;
 
+#ifdef XAD
+	/* We would rather use the keytab. */
+#else
 	if (!secrets_init()) {
 		DEBUG(1,("secrets_init failed\n"));
 		return NT_STATUS_LOGON_FAILURE;
@@ -61,6 +64,7 @@
 
 	password.data = password_s;
 	password.length = strlen(password_s);
+#endif /* XAD */
 
 	ret = krb5_init_context(&context);
 	if (ret) {
@@ -92,12 +96,6 @@
 		return NT_STATUS_LOGON_FAILURE;
 	}
 
-	ret = krb5_principal2salt(context, host_princ, &salt);
-	if (ret) {
-		DEBUG(1,("krb5_principal2salt failed (%s)\n", error_message(ret)));
-		return NT_STATUS_LOGON_FAILURE;
-	}
-    
 	if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) {
 		return NT_STATUS_NO_MEMORY;
 	}
@@ -110,14 +108,14 @@
 
 	/* we need to setup a auth context with each possible encoding type in turn */
 	for (i=0;enctypes[i];i++) {
-		krb5_use_enctype(context, &eblock, enctypes[i]);
-
-		ret = krb5_string_to_key(context, &eblock, key, &password, &salt);
+#ifndef XAD
+		ret = create_kerberos_key_from_string(context, host_princ, &password, key);
 		if (ret) {
 			continue;
 		}
 
 		krb5_auth_con_setuseruserkey(context, auth_context, key);
+#endif /* XAD */
 
 		packet.length = ticket->length;
 		packet.data = (krb5_pointer)ticket->data;
@@ -136,25 +134,34 @@
 		return NT_STATUS_LOGON_FAILURE;
 	}
 
-#if 0
-	file_save("/tmp/ticket.dat", ticket->data, ticket->length);
-#endif
-
-
-	if (tkt->enc_part2) {
-		*auth_data = data_blob(tkt->enc_part2->authorization_data[0]->contents,
-				       tkt->enc_part2->authorization_data[0]->length);
+	memset(session_key, 0, 16);
+	skey = NULL;
+	krb5_auth_con_getremotesubkey(context, auth_context, &skey);
+	if (skey == NULL) {
+		krb5_auth_con_getlocalsubkey(context, auth_context, &skey);
+	}
+	if (skey == NULL) {
+		krb5_auth_con_getkey(context, auth_context, &skey);
+	}
+	if (skey != NULL) {
+		if (skey->keytype != KEYTYPE_ARCFOUR && skey->keytype != KEYTYPE_ARCFOUR_56) {
+			DEBUG(3,("could not extract RC4 session key from Kerberos authenticator: "
+				"incorrect key type (%d)\n", skey->keytype));
+		} else {
+			if (skey->keyvalue.length == 16) {
+				memcpy(session_key, skey->keyvalue.data, skey->keyvalue.length);
+				DEBUG(3,("extracted RC4 session key from Kerberos authenticator\n"));
+			} else {
+				DEBUG(3,("could not extract RC4 session key from Kerberos authenticator: "
+					"incorrect length (%d bytes)\n", skey->keyvalue.length));
+			}
+		}
+		krb5_free_keyblock(context, skey);
 	}
 
-#if 0
-	if (tkt->enc_part2) {
-		file_save("/tmp/authdata.dat", 
-			  tkt->enc_part2->authorization_data[0]->contents,
-			  tkt->enc_part2->authorization_data[0]->length);
-	}
-#endif
+	get_auth_data_from_tkt(auth_data, tkt);
 
-	if ((ret = krb5_unparse_name(context, tkt->enc_part2->client, principal))) {
+	if ((ret = krb5_unparse_name(context, get_principal_from_tkt(tkt), principal))) {
 		DEBUG(3,("krb5_unparse_name failed (%s)\n", 
 			 error_message(ret)));
 		return NT_STATUS_LOGON_FAILURE;
Index: libsmb/clikrb5.c
===================================================================
RCS file: /cvsroot/samba/source/libsmb/clikrb5.c,v
retrieving revision 1.27
diff -u -r1.27 clikrb5.c
--- libsmb/clikrb5.c	30 Jan 2003 18:01:23 -0000	1.27
+++ libsmb/clikrb5.c	2 Feb 2003 00:00:41 -0000
@@ -43,6 +43,20 @@
 }
 #endif
 
+#ifndef HAVE_KRB5_FREE_KTYPES
+ void krb5_free_ktypes(krb5_context context, krb5_enctype *enctypes)
+{
+	free(enctypes);
+}
+#endif
+
+#if defined(HAVE_KRB5_GET_DEFAULT_IN_TKT_ETYPES) && !defined(HAVE_KRB5_GET_PERMITTED_ENCTYPES)
+ krb5_error_code krb5_get_permitted_enctypes(krb5_context context, krb5_enctype **enctypes)
+{
+	return krb5_get_default_in_tkt_etypes(context, enctypes);
+}
+#endif
+
 #if defined(HAVE_KRB5_SET_DEFAULT_IN_TKT_ETYPES) && !defined(HAVE_KRB5_SET_DEFAULT_TGS_KTYPES)
  krb5_error_code krb5_set_default_tgs_ktypes(krb5_context ctx, const krb5_enctype *enc)
 {

Index: passdb/secrets.c
===================================================================
RCS file: /cvsroot/samba/source/passdb/secrets.c,v
retrieving revision 1.54
diff -u -r1.54 secrets.c
--- passdb/secrets.c	1 Feb 2003 04:39:15 -0000	1.54
+++ passdb/secrets.c	2 Feb 2003 00:00:41 -0000
@@ -221,6 +221,66 @@
 	return True;
 }
 
+#ifdef XAD
+/************************************************************************
+ 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;
+	}
+
+	ret = krb5_kt_read_service_key(context, NULL, princ, 0, ENCTYPE_ARCFOUR_HMAC_MD5, &key);
+	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 /* XAD */
+
 /************************************************************************
  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 +303,12 @@
 		pass_last_set_time = 0;
 		return True;
 	}
+
+#ifdef XAD
+	if (!strcasecmp(domain, lp_workgroup())) {
+		return secrets_fetch_keytab_password(ret_pwd, pass_last_set_time);
+	}
+#endif
 
 	if (!(pass = secrets_fetch(trust_keystr(domain), &size))) {
 		DEBUG(5, ("secrets_fetch failed!\n"));
Index: rpc_server/srv_pipe_hnd.c
===================================================================
RCS file: /cvsroot/samba/source/rpc_server/srv_pipe_hnd.c,v
retrieving revision 1.84
diff -u -r1.84 srv_pipe_hnd.c
--- rpc_server/srv_pipe_hnd.c	20 Dec 2002 20:23:05 -0000	1.84
+++ rpc_server/srv_pipe_hnd.c	2 Feb 2003 00:00:42 -0000
@@ -69,6 +69,13 @@
 static void *make_internal_rpc_pipe_p(char *pipe_name, 
 			      connection_struct *conn, uint16 vuid);
 
+#ifdef NCALRPC_FUNNEL
+void *ncalrpc_make_funnel(char *pipe_name, connection_struct *conn, uint16 vuid);
+ssize_t ncalrpc_read_from_funnel(void *np_conn, char *data, size_t n, BOOL *is_data_outstanding);
+ssize_t ncalrpc_write_to_funnel(void *np_conn, char *data, size_t n);
+BOOL ncalrpc_close_funnel(void *np_conn);
+#endif /* NCALRPC_FUNNEL */
+
 /****************************************************************************
  Pipe iterator functions.
 ****************************************************************************/
@@ -214,11 +221,24 @@
 	ZERO_STRUCTP(p);
 
 	/* add a dso mechanism instead of this, here */
-
+#ifdef NCALRPC_FUNNEL
+	/* cleanup */
+	if (strequal(pipe_name, "lsarpc") ||
+	    strequal(pipe_name, "samr") ||
+	    strequal(pipe_name, "NETLOGON")) {
+		p->namedpipe_create = ncalrpc_make_funnel;
+		p->namedpipe_read = ncalrpc_read_from_funnel;
+		p->namedpipe_write = ncalrpc_write_to_funnel;
+		p->namedpipe_close = ncalrpc_close_funnel;
+	} else {
+#endif /* NCALRPC_FUNNEL */
 	p->namedpipe_create = make_internal_rpc_pipe_p;
 	p->namedpipe_read = read_from_internal_pipe;
 	p->namedpipe_write = write_to_internal_pipe;
 	p->namedpipe_close = close_internal_rpc_pipe_hnd;
+#ifdef NCALRPC_FUNNEL
+	}
+#endif /* NCALRPC_FUNNEL */
 
 	p->np_state = p->namedpipe_create(pipe_name, conn, vuid);
 
@@ -1159,3 +1179,4 @@
 
 	return NULL;
 }
+
Index: smbd/sesssetup.c
===================================================================
RCS file: /cvsroot/samba/source/smbd/sesssetup.c,v
retrieving revision 1.85
diff -u -r1.85 sesssetup.c
--- smbd/sesssetup.c	28 Jan 2003 11:51:55 -0000	1.85
+++ smbd/sesssetup.c	2 Feb 2003 00:00:42 -0000
@@ -148,6 +148,7 @@
 	DATA_BLOB auth_data;
 	auth_serversupplied_info *server_info = NULL;
 	ADS_STRUCT *ads;
+	uint8 session_key[16];
 
 	if (!spnego_parse_krb5_wrap(*secblob, &ticket)) {
 		return ERROR_NT(NT_STATUS_LOGON_FAILURE);
@@ -161,7 +162,7 @@
 
 	ads->auth.realm = strdup(lp_realm());
 
-	ret = ads_verify_ticket(ads, &ticket, &client, &auth_data);
+	ret = ads_verify_ticket(ads, &ticket, &client, &auth_data, session_key);
 	if (!NT_STATUS_IS_OK(ret)) {
 		DEBUG(1,("Failed to verify incoming ticket!\n"));	
 		ads_destroy(&ads);
@@ -218,7 +219,10 @@
 		DEBUG(1,("make_server_info_from_pw failed!\n"));
 		return ERROR_NT(ret);
 	}
-	
+
+	/* Copy out the session key from the AP_REQ. */
+	memcpy(server_info->session_key, session_key, sizeof(session_key));
+
 	sess_vuid = register_vuid(server_info, user);
 
 	free(user);
-------------- next part --------------

--
Luke Howard | PADL Software Pty Ltd | www.padl.com


More information about the samba-technical mailing list