[3010] in Kerberos-V5-bugs

home help back first fref pref prev next nref lref last post

krb5-kdc/668: SAM preauth fixes

daemon@ATHENA.MIT.EDU (fcusack@iconnet.net)
Mon Nov 30 21:06:15 1998

Resent-From: gnats@rt-11.MIT.EDU (GNATS Management)
Resent-To: krb5-unassigned@RT-11.MIT.EDU
Resent-Reply-To: krb5-bugs@MIT.EDU, fcusack@iconnet.net
Date: Mon, 30 Nov 1998 21:06:33 -0500 (EST)
From: fcusack@iconnet.net
Reply-To: fcusack@iconnet.net
To: krb5-bugs@MIT.EDU
Cc: fcusack@iconnet.net


>Number:         668
>Category:       krb5-kdc
>Synopsis:       unify sam_track_id data; securid fixes
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    krb5-unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   unknown
>Arrival-Date:   Mon Nov 30 21:06:01 EST 1998
>Last-Modified:
>Originator:     Frank Cusack
>Organization:
Icon CMT Corp.
>Release:        krb5-current-19981119
>Environment:
N/A
System: SunOS ratbert 5.6 Generic_105181-09 sun4u sparc SUNW,Ultra-5_10
Architecture: sun4

>Description:
	Some fixes related to my previous pr's. This should be applied
	along with krb5-kdc/662-665.

	Fixes in this pr "unify" the predicted_sam_response so that the
	same data type can be used for all sam mechanisms. It adds
	a field `msd' which is `mechanism specific data' to the "psr".

	Also, prototype changes for the sam_verify_xxx functions needed
	for securid (for send-encrypted-sad in general).

	Also, a bunch of securid fixes. Securid should work now, although
	I am unable to test at this time.
>How-To-Repeat:
>Fix:
Index: include/k5-int.h
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/include/k5-int.h,v
retrieving revision 1.5
diff -u -r1.5 k5-int.h
--- k5-int.h	1998/11/25 22:35:55	1.5
+++ k5-int.h	1998/12/01 02:00:03
@@ -344,17 +344,11 @@
 #define PA_SAM_TYPE_GRAIL		(PA_SAM_TYPE_EXP_BASE+0) /* testing */
 #define PA_SAM_TYPE_SECURID_PREDICT	(PA_SAM_TYPE_EXP_BASE+1) /* special */
 
-typedef struct _krb5_rb1_track_data {
-	krb5_magic	magic;
-	krb5_keyblock	sam_key;
-	krb5_data	next_challenge;
-	krb5_int32	kdc_id; /* some magic to avoid esre replays */
-} krb5_rb1_track_data;
-
 typedef struct _krb5_predicted_sam_response {
 	krb5_magic	magic;
 	krb5_keyblock	sam_key;
 	krb5_int32	kdc_id; /* some magic to avoid esre replays */
+	krb5_data	msd;	/* mechanism specific data */
 } krb5_predicted_sam_response;
 
 typedef struct _krb5_sam_challenge {
@@ -961,8 +955,6 @@
 	KRB5_PROTOTYPE((krb5_context, krb5_predicted_sam_response FAR * ));
 KRB5_DLLIMP void KRB5_CALLCONV krb5_free_enc_sam_response_enc
 	KRB5_PROTOTYPE((krb5_context, krb5_enc_sam_response_enc FAR * ));
-KRB5_DLLIMP void KRB5_CALLCONV krb5_free_rb1_track_data
-	KRB5_PROTOTYPE((krb5_context, krb5_rb1_track_data FAR * ));
 KRB5_DLLIMP void KRB5_CALLCONV krb5_free_sam_challenge_contents
 	KRB5_PROTOTYPE((krb5_context, krb5_sam_challenge FAR * ));
 KRB5_DLLIMP void KRB5_CALLCONV krb5_free_sam_response_contents
@@ -971,8 +963,6 @@
 	KRB5_PROTOTYPE((krb5_context, krb5_predicted_sam_response FAR * ));
 KRB5_DLLIMP void KRB5_CALLCONV krb5_free_enc_sam_response_enc_contents
 	KRB5_PROTOTYPE((krb5_context, krb5_enc_sam_response_enc FAR * ));
-KRB5_DLLIMP void KRB5_CALLCONV krb5_free_rb1_track_data_contents
-	KRB5_PROTOTYPE((krb5_context, krb5_rb1_track_data FAR * ));
 
 KRB5_DLLIMP void KRB5_CALLCONV krb5_free_pa_enc_ts
 	KRB5_PROTOTYPE((krb5_context, krb5_pa_enc_ts FAR *));
@@ -1216,9 +1206,6 @@
 krb5_error_code encode_krb5_predicted_sam_response
        KRB5_PROTOTYPE((const krb5_predicted_sam_response * , krb5_data **));
 
-krb5_error_code encode_krb5_rb1_track_data
-	KRB5_PROTOTYPE((const krb5_rb1_track_data *, krb5_data **));
-
 /*************************************************************************
  * End of prototypes for krb5_encode.c
  *************************************************************************/
@@ -1237,9 +1224,6 @@
 
 krb5_error_code decode_krb5_predicted_sam_response
        KRB5_PROTOTYPE((const krb5_data *, krb5_predicted_sam_response **));
-
-krb5_error_code decode_krb5_rb1_track_data
-	KRB5_PROTOTYPE((const krb5_data *, krb5_rb1_track_data **));
 
 
 /*************************************************************************
Index: include/krb5/kdb.h
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/include/krb5/kdb.h,v
retrieving revision 1.2
diff -u -r1.2 kdb.h
--- kdb.h	1998/11/25 06:50:48	1.2
+++ kdb.h	1998/12/01 02:00:03
@@ -145,9 +145,6 @@
 #define KRB5_TL_KADM_DATA		0x0003
 #define KRB5_TL_KADM5_E_DATA		0x0004
 #define KRB5_TL_RB1_CHALLENGE		0x0005
-#ifdef SECURID
-#define KRB5_TL_SECURID_STATE           0x0006
-#endif /* SECURID */
     
 /*
  * Determines the number of failed KDC requests before DISALLOW_ALL_TIX is set
Index: kdc/preauth/pa_sam.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/kdc/preauth/pa_sam.c,v
retrieving revision 1.1
diff -u -r1.1 pa_sam.c
--- pa_sam.c	1998/11/25 04:06:17	1.1
+++ pa_sam.c	1998/12/01 02:00:04
@@ -255,7 +255,7 @@
 	return retval;
     }
 
-    retval = (sam_inst_map[sam_index].generate_proc)(context, request, assoc,
+    retval = (sam_inst_map[sam_index].generate_proc)(context, request, &assoc,
 						     npr, sam_key, client_key,
 						     sam_inst_map[sam_index].mode,
 						     pa_data);
@@ -298,7 +298,8 @@
 	goto cleanup;
     }
 
-    retval = (sam_inst_map[sam_index].verify_proc)(context, request, assoc, npr,
+    retval = (sam_inst_map[sam_index].verify_proc)(context, request, client,
+						   &assoc, npr,
 						   sam_inst_map[sam_index].mode,
 						   sr, enc_tkt_reply, as_key);
     krb5_db_free_principal(kdc_context, &assoc, npr);
Index: kdc/preauth/pa_sam.h
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/kdc/preauth/pa_sam.h,v
retrieving revision 1.2
diff -u -r1.2 pa_sam.h
--- pa_sam.h	1998/11/25 23:34:39	1.2
+++ pa_sam.h	1998/12/01 02:00:04
@@ -31,7 +31,7 @@
 typedef krb5_error_code (*sam_generate_proc)
     KRB5_PROTOTYPE((krb5_context context,
 		    krb5_kdc_req *request,
-		    krb5_db_entry assoc,
+		    krb5_db_entry *assoc,
 		    int npr,
 		    krb5_keyblock sam_key,
 		    krb5_keyblock client_key,
@@ -41,7 +41,8 @@
 typedef krb5_error_code (*sam_verify_proc)
     KRB5_PROTOTYPE((krb5_context,
 		    krb5_kdc_req *request,
-		    krb5_db_entry assoc,
+		    krb5_db_entry *client, /* client db_entry */
+		    krb5_db_entry *assoc,  /* sam db_entry */
 		    int npr,
 		    int sam_mode,
 		    krb5_sam_response *sr,
@@ -59,7 +60,7 @@
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV sam_generate_grail
     KRB5_PROTOTYPE((krb5_context,
 		    krb5_kdc_req *request,
-		    krb5_db_entry assoc,
+		    krb5_db_entry *assoc,
 		    int npr,
 		    krb5_keyblock sam_key,
 		    krb5_keyblock client_key,
@@ -68,7 +69,8 @@
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV sam_verify_grail
     KRB5_PROTOTYPE((krb5_context,
 		    krb5_kdc_req *request,
-		    krb5_db_entry assoc,
+		    krb5_db_entry *client,
+		    krb5_db_entry *assoc,
 		    int npr,
 		    int mode,
 		    krb5_sam_response *sr,
@@ -78,7 +80,7 @@
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV sam_generate_enigma
     KRB5_PROTOTYPE((krb5_context,
 		    krb5_kdc_req *request,
-		    krb5_db_entry assoc,
+		    krb5_db_entry *assoc,
 		    int npr,
 		    krb5_keyblock sam_key,
 		    krb5_keyblock client_key,
@@ -87,7 +89,8 @@
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV sam_verify_enigma
     KRB5_PROTOTYPE((krb5_context,
 		    krb5_kdc_req *request,
-		    krb5_db_entry assoc,
+		    krb5_db_entry *client,
+		    krb5_db_entry *assoc,
 		    int npr,
 		    int mode,
 		    krb5_sam_response *sr,
@@ -97,7 +100,7 @@
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV sam_generate_digi_path
     KRB5_PROTOTYPE((krb5_context,
 		    krb5_kdc_req *request,
-		    krb5_db_entry assoc,
+		    krb5_db_entry *assoc,
 		    int npr,
 		    krb5_keyblock sam_key,
 		    krb5_keyblock client_key,
@@ -106,7 +109,8 @@
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV sam_verify_digi_path
     KRB5_PROTOTYPE((krb5_context,
 		    krb5_kdc_req *request,
-		    krb5_db_entry assoc,
+		    krb5_db_entry *client,
+		    krb5_db_entry *assoc,
 		    int npr,
 		    int mode,
 		    krb5_sam_response *sr,
@@ -116,7 +120,7 @@
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV sam_generate_skey
     KRB5_PROTOTYPE((krb5_context,
 		    krb5_kdc_req *request,
-		    krb5_db_entry assoc,
+		    krb5_db_entry *assoc,
 		    int npr,
 		    krb5_keyblock sam_key,
 		    krb5_keyblock client_key,
@@ -125,7 +129,8 @@
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV sam_verify_skey
     KRB5_PROTOTYPE((krb5_context,
 		    krb5_kdc_req *request,
-		    krb5_db_entry assoc,
+		    krb5_db_entry *client,
+		    krb5_db_entry *assoc,
 		    int npr,
 		    int mode,
 		    krb5_sam_response *sr,
@@ -135,7 +140,7 @@
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV sam_generate_securid
     KRB5_PROTOTYPE((krb5_context,
 		    krb5_kdc_req *request,
-		    krb5_db_entry assoc,
+		    krb5_db_entry *assoc,
 		    int npr,
 		    krb5_keyblock sam_key,
 		    krb5_keyblock client_key,
@@ -144,7 +149,8 @@
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV sam_verify_securid
     KRB5_PROTOTYPE((krb5_context,
 		    krb5_kdc_req *request,
-		    krb5_db_entry assoc,
+		    krb5_db_entry *client,
+		    krb5_db_entry *assoc,
 		    int npr,
 		    int mode,
 		    krb5_sam_response *sr,
@@ -154,7 +160,7 @@
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV sam_generate_cryptocard
     KRB5_PROTOTYPE((krb5_context,
 		    krb5_kdc_req *request,
-		    krb5_db_entry assoc,
+		    krb5_db_entry *assoc,
 		    int npr,
 		    krb5_keyblock sam_key,
 		    krb5_keyblock client_key,
@@ -163,7 +169,8 @@
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV sam_verify_cryptocard
     KRB5_PROTOTYPE((krb5_context,
 		    krb5_kdc_req *request,
-		    krb5_db_entry assoc,
+		    krb5_db_entry *client,
+		    krb5_db_entry *assoc,
 		    int npr,
 		    int mode,
 		    krb5_sam_response *sr,
Index: kdc/preauth/pa_sam_cryptocard.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/kdc/preauth/pa_sam_cryptocard.c,v
retrieving revision 1.5
diff -u -r1.5 pa_sam_cryptocard.c
--- pa_sam_cryptocard.c	1998/11/25 23:34:40	1.5
+++ pa_sam_cryptocard.c	1998/12/01 02:00:05
@@ -34,7 +34,7 @@
 			mode, pa_data)
     krb5_context 	context;
     krb5_kdc_req *	request;
-    krb5_db_entry	assoc;
+    krb5_db_entry *	assoc;
     int			npr;
     krb5_keyblock	sam_key;
     krb5_keyblock	client_key;
@@ -43,7 +43,7 @@
 {
     krb5_error_code		retval;
     krb5_sam_challenge		sc;
-    krb5_rb1_track_data		rb1_track_data;
+    krb5_predicted_sam_response	psr;
     krb5_tl_data		tl_data;
 
     krb5_data *			scratch;
@@ -55,10 +55,11 @@
     char			inputblock[8];
     char			outputblock[8];
     char			response[9];
+    char			next_challenge[8];
     krb5_data			predict_response;
 
     memset(&sc, 0, sizeof(sc));
-    memset(&rb1_track_data, 0, sizeof(rb1_track_data));
+    memset(&psr, 0, sizeof(psr));
     memset(inputblock, 0, 8);
     session_key.contents = 0;
 
@@ -78,7 +79,7 @@
      * (Event Synchronous mode)
      */
     tl_data.tl_data_type = KRB5_TL_RB1_CHALLENGE;
-    if ((retval = krb5_dbe_lookup_tl_data(kdc_context, &assoc, &tl_data)) ||
+    if ((retval = krb5_dbe_lookup_tl_data(kdc_context, assoc, &tl_data)) ||
 	(tl_data.tl_data_length == 0)) {
 #endif /* KRBCONF_KDC_MODIFIES_KDB */
 	/*
@@ -224,18 +225,13 @@
 	 * Simply take the full encrypted response block, convert it
 	 * to ASCII numerals, and convert 0xa - 0xf to 0x0 - 0x05
 	 */
-	if ((rb1_track_data.next_challenge.data = malloc(8)) == NULL) {
-	    retval = ENOMEM;
-	    goto cleanup;
-	}
-
-	rb1_track_data.next_challenge.length = 8;
 	for (i = 0; i < 8; i++) {
-	    rb1_track_data.next_challenge.data[i] =
-		(outputblock[i] & 0x0f) | 0x30;
-	    if (rb1_track_data.next_challenge.data[i] > 0x39)
-		rb1_track_data.next_challenge.data[i] -= 10;
+	    next_challenge[i] = (outputblock[i] & 0x0f) | 0x30;
+	    if (next_challenge[i] > 0x39)
+		next_challenge[i] -= 10;
 	}
+	psr.msd.length = 8;
+	psr.msd.data = &next_challenge[0];
         break;
 
     case RB1_MODE_H8_RC:
@@ -247,11 +243,11 @@
 #endif /* KRBCONF_KDC_MODIFIES_KDB */
 
     /* Convert the SAD into a key. */
-    rb1_track_data.magic = KV5M_PREDICTED_SAM_RESPONSE;
-    rb1_track_data.kdc_id = kdc_id;
+    psr.magic = KV5M_PREDICTED_SAM_RESPONSE;
+    psr.kdc_id = kdc_id;
     if (retval = krb5_c_string_to_key(context, ENCTYPE_DES_CBC_MD5,
 				      &predict_response, 0 /* salt */,
-				      &rb1_track_data.sam_key)) {
+				      &psr.sam_key)) {
 	goto cleanup;
     }
 
@@ -259,23 +255,31 @@
     /* And XOR with the principal's long term key (in place). */
     /* XXX There should be an abstraction for this ... */
     {
-	krb5_octet *p = rb1_track_data.sam_key.contents;
+	krb5_octet *p = psr.sam_key.contents;
 	krb5_octet *q = client_key.contents;
 
-	for (i = 0; i < rb1_track_data.sam_key.length; i++)
+	for (i = 0; i < psr.sam_key.length; i++)
 	    p[i] ^= q[i];
     }
-    mit_des_fixup_key_parity(rb1_track_data.sam_key.contents);
-    if (mit_des_is_weak_key(rb1_track_data.sam_key.contents))
-	((krb5_octet *) rb1_track_data.sam_key.contents)[7] ^= 0xf0;
+    mit_des_fixup_key_parity(psr.sam_key.contents);
+    if (mit_des_is_weak_key(psr.sam_key.contents))
+	((krb5_octet *) psr.sam_key.contents)[7] ^= 0xf0;
 #endif /* !AS_REP_105_SAM_COMPAT */
 
     /*
      * Now we have an encrypting key that the client will use for
      * the sam response, and that the KDC should use for the AP_REP.
      */
-    if (retval = encode_krb5_rb1_track_data(&rb1_track_data, &scratch))
+    if (retval = encode_krb5_predicted_sam_response(&psr, &scratch)) {
+	/* Don't free this, it's static (automatic). */
+	psr.msd.data = NULL;
+	psr.msd.length = 0;
 	goto cleanup;
+    }
+  
+    /* Don't free this, it's static (automatic). */
+    psr.msd.data = NULL;
+    psr.msd.length = 0;
 
     if (retval = krb5_c_encrypt_length(context, master_keyblock.enctype,
 				       scratch->length, &enclen)) {
@@ -313,8 +317,8 @@
     if (retval = krb5_calculate_checksum(context, CKSUMTYPE_RSA_MD5_DES,
 					 sc.sam_challenge.data,
 					 sc.sam_challenge.length,
-			/* key */	 rb1_track_data.sam_key.contents,
-			/* key length */ rb1_track_data.sam_key.length,
+			/* key */	 psr.sam_key.contents,
+			/* key length */ psr.sam_key.length,
 					 &sc.sam_cksum)) {
 	goto cleanup;
     }
@@ -337,14 +341,11 @@
     krb5_free_data(context, scratch);
 
 cleanup:
-    if (rb1_track_data.sam_key.contents)
-	krb5_free_keyblock_contents(context, &rb1_track_data.sam_key);
-    if (rb1_track_data.next_challenge.data)
-	krb5_xfree(rb1_track_data.next_challenge.data);
+    krb5_free_predicted_sam_response_contents(context, &psr);
 
     /* Don't use the abstraction to free sc; most of it is static. */
-    if (sc.sam_track_id.data);
-	krb5_free_data_contents(context, &sc.sam_track_id);
+    if (sc.sam_track_id.data)
+	krb5_xfree(sc.sam_track_id.data);
     if (sc.sam_cksum.contents)
 	krb5_xfree(sc.sam_cksum.contents);
 
@@ -356,25 +357,26 @@
 
 
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-sam_verify_cryptocard(context, request, assoc, npr, mode, sr, enc_tkt_reply,
-		      as_key)
+sam_verify_cryptocard(context, request, client, assoc, npr, mode, sr,
+		      enc_tkt_reply, as_key)
     krb5_context	context;
     krb5_kdc_req *	request;
-    krb5_db_entry	assoc;
+    krb5_db_entry *	client;
+    krb5_db_entry *	assoc;
     int			npr;
     int			mode;
     krb5_sam_response *	sr;
     krb5_enc_tkt_part *	enc_tkt_reply;
     krb5_keyblock *	as_key;
 {
-    krb5_error_code		retval;
-    krb5_data			scratch;
-    krb5_enc_data		tmpdata;
-    krb5_tl_data		tl_data;
-
-    krb5_rb1_track_data	*	rb1_track_data = 0;
-    krb5_enc_sam_response_enc *	esre = 0;
-    krb5_timestamp		timenow;
+    krb5_error_code			retval;
+    krb5_data				scratch;
+    krb5_enc_data			tmpdata;
+    krb5_tl_data			tl_data;
+
+    krb5_predicted_sam_response	*	psr = 0;
+    krb5_enc_sam_response_enc *		esre = 0;
+    krb5_timestamp			timenow;
 
     /* Sanity check */
     if (sr->sam_type != PA_SAM_TYPE_CRYPTOCARD) {
@@ -405,14 +407,14 @@
 	goto cleanup;
     }
 
-    retval = decode_krb5_rb1_track_data(&scratch, &rb1_track_data);
+    retval = decode_krb5_predicted_sam_response(&scratch, &psr);
     krb5_xfree(scratch.data);
     if (retval) {
-	com_err("krb5kdc", retval, "decode_krb5_rb1_track_data failed");
+	com_err("krb5kdc", retval, "decode_krb5_predicted_sam_response failed");
 	goto cleanup;
     }
 
-    if (rb1_track_data->kdc_id != kdc_id) {
+    if (psr->kdc_id != kdc_id) {
 	com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
 		"Warning - possible SAM replay attack!");
 	goto cleanup;
@@ -429,8 +431,8 @@
 	goto cleanup;
     }
 
-    /* Now use rb1_track_data->sam_key to verify */
-    if (retval = krb5_c_decrypt(context, &rb1_track_data->sam_key,
+    /* Now use psr->sam_key to verify */
+    if (retval = krb5_c_decrypt(context, &psr->sam_key,
 				/* XXX */ 0, 0,
 				&sr->sam_enc_nonce_or_ts, &scratch)) {
 	com_err("krb5kdc", retval, "decrypt nonce_or_ts failed");
@@ -459,25 +461,25 @@
     }
 
     /* Success! Make sure we use the sam_key for the AS_REP. */
-    krb5_copy_keyblock_contents(context, &rb1_track_data->sam_key, as_key);
+    krb5_copy_keyblock_contents(context, &psr->sam_key, as_key);
 
 #ifdef KRBCONF_KDC_MODIFIES_KDB
     /* Save the next challenge, if present. */
-    if (rb1_track_data->next_challenge.length == 8) {
+    if (psr->msd.length == 8) {
 	tl_data.tl_data_type = KRB5_TL_RB1_CHALLENGE;
-	tl_data.tl_data_length = rb1_track_data->next_challenge.length;
-	tl_data.tl_data_contents = rb1_track_data->next_challenge.data;
+	tl_data.tl_data_length = psr->msd.length;
+	tl_data.tl_data_contents = psr->msd.data;
 
-	if (retval = krb5_dbe_update_tl_data(kdc_context, &assoc, &tl_data))
+	if (retval = krb5_dbe_update_tl_data(kdc_context, assoc, &tl_data))
 	    com_err("krb5kdc", retval, "while updating RB-1 challenge tl_data");
-	if (retval = krb5_db_put_principal(kdc_context, &assoc, &npr))
+	if (retval = krb5_db_put_principal(kdc_context, assoc, &npr))
 	    com_err("krb5kdc", retval, "while storing RB-1 challenge tl_data");
     }
 #endif /* KRBCONF_KDC_MODIFIES_KDB */
 
 cleanup:
-    if (rb1_track_data)
-	krb5_free_rb1_track_data(context, rb1_track_data);
+    if (psr)
+	krb5_free_predicted_sam_response(context, psr);
     if (esre) 
 	krb5_free_enc_sam_response_enc(context, esre);
 
Index: kdc/preauth/pa_sam_digi_path.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/kdc/preauth/pa_sam_digi_path.c,v
retrieving revision 1.5
diff -u -r1.5 pa_sam_digi_path.c
--- pa_sam_digi_path.c	1998/11/25 23:34:40	1.5
+++ pa_sam_digi_path.c	1998/12/01 02:00:06
@@ -34,7 +34,7 @@
 		       mode, pa_data)
     krb5_context 	context;
     krb5_kdc_req *	request;
-    krb5_db_entry	assoc;
+    krb5_db_entry *	assoc;
     int			npr;
     krb5_keyblock	sam_key;
     krb5_keyblock	client_key;
@@ -245,7 +245,7 @@
     krb5_free_predicted_sam_response_contents(context, &psr);
 
     /* Don't use the abstraction to free sc; most of it is static. */
-    if (sc.sam_track_id.data);
+    if (sc.sam_track_id.data)
 	krb5_xfree(sc.sam_track_id.data);
     if (sc.sam_cksum.contents)
 	krb5_xfree(sc.sam_cksum.contents);
@@ -258,11 +258,12 @@
 
 
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-sam_verify_digi_path(context, request, assoc, npr, mode, sr, enc_tkt_reply,
-		     as_key)
+sam_verify_digi_path(context, request, client, assoc, npr, mode, sr,
+		     enc_tkt_reply, as_key)
     krb5_context	context;
     krb5_kdc_req *	request;
-    krb5_db_entry	assoc;
+    krb5_db_entry *	client;
+    krb5_db_entry *	assoc;
     int			npr;
     int			mode;
     krb5_sam_response *	sr;
Index: kdc/preauth/pa_sam_enigma.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/kdc/preauth/pa_sam_enigma.c,v
retrieving revision 1.1
diff -u -r1.1 pa_sam_enigma.c
--- pa_sam_enigma.c	1998/11/25 04:06:18	1.1
+++ pa_sam_enigma.c	1998/12/01 02:00:06
@@ -33,7 +33,7 @@
 		   mode, pa_data)
     krb5_context 	context;
     krb5_kdc_req *	request;
-    krb5_db_entry	assoc;
+    krb5_db_entry *	assoc;
     int			npr;
     krb5_keyblock	sam_key;
     krb5_keyblock	client_key;
@@ -45,10 +45,12 @@
     
 
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-sam_verify_enigma(context, request, assoc, npr, mode, sr, enc_tkt_reply, as_key)
+sam_verify_enigma(context, request, client, assoc, npr, mode, sr,
+		  enc_tkt_reply, as_key)
     krb5_context	context;
     krb5_kdc_req *	request;
-    krb5_db_entry	assoc;
+    krb5_db_entry *	client;
+    krb5_db_entry *	assoc;
     int			npr;
     int			mode;
     krb5_sam_response *	sr;
Index: kdc/preauth/pa_sam_grail.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/kdc/preauth/pa_sam_grail.c,v
retrieving revision 1.3
diff -u -r1.3 pa_sam_grail.c
--- pa_sam_grail.c	1998/11/25 23:34:40	1.3
+++ pa_sam_grail.c	1998/12/01 02:00:06
@@ -34,7 +34,7 @@
 		   mode, pa_data)
     krb5_context 	context;
     krb5_kdc_req *	request;
-    krb5_db_entry	assoc;
+    krb5_db_entry *	assoc;
     int			npr;
     krb5_keyblock	sam_key;
     krb5_keyblock	client_key;
@@ -144,7 +144,7 @@
     krb5_free_predicted_sam_response_contents(context, &psr);
 
     /* Don't use the abstraction to free sc; most of it is static. */
-    if (sc.sam_track_id.data);
+    if (sc.sam_track_id.data)
 	krb5_xfree(sc.sam_track_id.data);
     if (sc.sam_cksum.contents)
 	krb5_xfree(sc.sam_cksum.contents);
@@ -160,10 +160,12 @@
  * data is stored in the predicted_sam_response.
  */
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-sam_verify_grail(context, request, assoc, npr, mode, sr, enc_tkt_reply, as_key)
+sam_verify_grail(context, request, client, assoc, npr, mode, sr,
+		 enc_tkt_reply, as_key)
     krb5_context	context;
     krb5_kdc_req *	request;
-    krb5_db_entry	assoc;
+    krb5_db_entry *	client;
+    krb5_db_entry *	assoc;
     int			npr;
     int			mode;
     krb5_sam_response *	sr;
Index: kdc/preauth/pa_sam_securid.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/kdc/preauth/pa_sam_securid.c,v
retrieving revision 1.4
diff -u -r1.4 pa_sam_securid.c
--- pa_sam_securid.c	1998/11/25 23:34:40	1.4
+++ pa_sam_securid.c	1998/12/01 02:00:06
@@ -29,17 +29,12 @@
 #include "pa_sam.h"
 
 
-/* XXX This code does not work yet. */
+/* XXX This code is untested, but should work. This module depends on
+   the KDC being single threaded (due to global state). */
 
 /*
- * XXX This code depends on the client contacting the same KDC with
- * a response containing pa_data as it initially contacted when it got
- * the KRB_ERROR message. This means this specifically will not work
- * with any kind of DNS load balancing/round-robin/etc.
+ * SecurID functionality stolen from securid.c:
  *
- * SecurID functionality stolen from securid.c: (modified to "eliminate"
- *                                               global state problems)
- *
  *     Author: Kenneth D. Renard
  *             Army Research Lab
  *       Date: 9 Oct 96
@@ -47,134 +42,123 @@
  */
 
 
-#if defined(SECURID) && defined(KRBCONF_KDC_MODIFIES_KDB)
+#if defined(SECURID)
 
 #include <sdi_athd.h>
 #include <sdi_defs.h>
 #include <sdconf.h>
 #include <sdacmvls.h>
 
-/*
- * XXX struct SD_CLIENT must not contain any pointers.
- * Also, kind of poor that we only support IP addresses.
- */
-typedef struct _krb5_securid_state {
+typedef struct _securid_track_data {
     krb5_int32		state;			/* states */
-    krb5_timestamp	tl_time;		/* to avoid stale data */
-    char		newpin[LENPRNST + 1];	/* for PIN verification */
+    char		passcode[LENPRNST + 1];	/* for PRN/PIN verification */
     struct SD_CLIENT	sd_info;		/* SecurID state info */
-    krb5_int32		kdc_id;			/* Keep sd_info local */
-} krb5_securid_state;
+} securid_track_data;
 
 union config_record configure;
 int need_to_creadcfg = 1;
 int need_to_sd_init = 1;
+
+static krb5_sam_challenge g_sc = { 0, };
+static securid_track_data g_sid_track_data = { SECURID_STATE_NONE, };
 
-#endif /* SECURID && KRBCONF_KDC_MODIFIES_KDB */
+#endif /* SECURID */
 
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
 sam_generate_securid(context, request, assoc, npr, sam_key, client_key,
 		     mode, pa_data)
     krb5_context 	context;
     krb5_kdc_req *	request;
-    krb5_db_entry	assoc;
+    krb5_db_entry *	assoc;
     int			npr;
     krb5_keyblock	sam_key;
     krb5_keyblock	client_key;
     int			mode;
     krb5_pa_data *	pa_data;
 {
-#if defined(SECURID) && defined(KRBCONF_KDC_MODIFIES_KDB)
+#if defined(SECURID)
     krb5_error_code		retval;
-    krb5_sam_challenge		sc;
     krb5_predicted_sam_response	psr;
 
     krb5_data *			scratch;
     krb5_enc_data		tmpdata;
     size_t			enclen;
-    krb5_tl_data		tl_data;
-    krb5_securid_state		securid_state;
-    krb5_timestamp		timenow;
-    int				update_tl_data = 0;
 
-    memset(&sc, 0, sizeof(sc));
     memset(&psr, 0, sizeof(psr));
 
-    sc.magic = KV5M_SAM_CHALLENGE;
-    sc.sam_type = PA_SAM_TYPE_SECURID;
-    sc.sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD;
-    sc.sam_type_name.data = "SecurID Authentication";
-    sc.sam_type_name.length = strlen(sc.sam_type_name.data);
-
-    /* Generate prompt based on current state. */
-    tl_data.tl_data_type = KRB5_TL_SECURID_STATE;
-    if ((retval = krb5_dbe_lookup_tl_data(kdc_context, &assoc, &tl_data)) ||
-	(tl_data.tl_data_length == 0)) {
-	if (tl_data.tl_data_length != sizeof(securid_state)) {
-	    com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
-		    "corrupted tl_data!");
-	    return retval;
-	}
-	memcpy(securid_state, tl_data.tl_data_contents, sizeof(securid_state));
+    /*
+     * g_sc and g_sid_track_data are reset when we exit this routine.
+     * If they have non-initial values, it is b/c it was just setup
+     * in the verify routine.
+     */
+    if (g_sc.magic == 0) {
+	g_sc.magic = KV5M_SAM_CHALLENGE;
+	g_sc.sam_type = PA_SAM_TYPE_SECURID;
+	g_sc.sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD;
+	g_sc.sam_type_name.data = "SecurID Authentication";
+	g_sc.sam_type_name.length = strlen(sc.sam_type_name.data);
+    }
+
+    switch (g_sid_track_data.state) {
+    case SECURID_STATE_NONE:
+	g_sid_track_data.state = SECURID_STATE_INITIAL;
+	g_sc.magic = KV5M_SAM_CHALLENGE;
+	g_sc.sam_type = PA_SAM_TYPE_SECURID;
+	g_sc.sam_flags = KRB5_SAM_SEND_ENCRYPTED_SAD;
+	g_sc.sam_type_name.data = "SecurID Authentication";
+	g_sc.sam_type_name.length = strlen(sc.sam_type_name.data);
+	g_sc.sam_challenge.data = NULL;
+	g_sc.sam_challenge.length = 0;
 
-	/*
-	 * Verify that the tl_data is not stale (from a user abort or
-	 * *shudder* possibly a crash). We have to use at least a one
-	 * minute window; a next PRN could take at least that long.
-	 */
-	if (retval = krb5_timeofday(context, &timenow))
-	    return retval;
-
-	if ((timenow - securid_state.tl_time) > 90) {
-	    memset(&securid_state, 0, sizeof(securid_state));
-	    securid_state.state = SECURID_STATE_INITIAL;
-	}
-
-	switch (securid_state.state) {
-	case SECURID_STATE_INITIAL:
-	    sc.sam_reponse_prompt.data = "SecurID Passcode";
-	    break;
+    case SECURID_STATE_INITIAL:
+	g_sc.sam_challenge_label.data = NULL;
+	g_sc.sam_challenge_label.length = 0;
+	g_sc.sam_response_prompt.data = "SecurID Passcode";
+	break;
 
-	case SECURID_STATE_NEXT_CODE:
-	    sc.sam_response_prompt.data = "Enter next Passcode";
-	    break;
+    case SECURID_STATE_NEXT_CODE:
+	g_sc.sam_challenge_label.data = NULL;
+	g_sc.sam_challenge_label.length = 0;
+	g_sc.sam_response_prompt.data = "Enter next Passcode";
+	break;
 
-	case SECURID_STATE_NEW_PIN:
-	    sc.sam_challenge_label.data = "Select a new PIN";
-	    sc.sam_challenge_label.length = strlen(sc.sam_challenge_label.data);
-	    sc.sam_response_prompt.data = "Enter new PIN";
-	    break;
+    case SECURID_STATE_NEW_PIN:
+	g_sc.sam_challenge_label.data = "Select a new PIN";
+	g_sc.sam_challenge_label.length = strlen(sc.sam_challenge_label.data);
+	g_sc.sam_response_prompt.data = "Enter new PIN";
+	break;
 
-	case SECURID_STATE_NEW_PIN_AGAIN:
-	    sc.sam_response_prompt.data = "Verify the new PIN";
-	    break;
+    case SECURID_STATE_NEW_PIN_AGAIN:
+	g_sc.sam_challenge_label.data = "Verify the new PIN";
+	g_sc.sam_challenge_label.length = strlen(sc.sam_challenge_label.data);
+	g_sc.sam_response_prompt.data = "Enter the new PIN again";
+	break;
 
-	default:
-	    com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
-		    "bad state in securid track_data");
-	    return retval;
-	} /* switch (securid_state) */
-    } else {
-	/* tl_data not found, this is a new user. */
-	sc.sam_reponse_prompt.data = "SecurID Passcode";
-    }
-    sc.sam_response_prompt.length = strlen(sc.sam_challenge_label.data);
+    default:
+	com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
+		"bad state in g_sid_track_data");
+	return retval;
+    } /* switch (g_sid_track_data.state) */
+    g_sc.sam_response_prompt.length = strlen(g_sc.sam_response_prompt.data);
 
-    /*
-     * XXX Note that for states that require multiple transactions,
-     * the KRB_ERROR will always come from the same KDC that the
-     * first AS_REQ goes to; this is b/c this code runs right after
-     * the verify code in those states. Thus, we only have to check
-     * the kdc_id in the verify code.
-     */
     psr.magic = KV5M_PREDICTED_SAM_RESPONSE;
     psr.kdc_id = kdc_id;
-    /* Encrypt with longterm key (send-encrypted-sad). */
+    psr.msd.data = &g_sid_track_data;
+    psr.msd.length = sizeof(g_sid_track_data);
+    /* esre will be encrypted w/ client longterm key (send-encrypted-sad) */
     krb5_copy_keyblock_contents(context, &client_key, &psr.sam_key);
 
-    if (retval = encode_krb5_predicted_sam_response(&psr, &scratch))
+    if (retval = encode_krb5_predicted_sam_response(&psr, &scratch)) {
+	/* Don't free this, it's static. */
+	psr.msd.data = NULL;
+	psr.msd.length = 0;
 	goto cleanup;
+    }
 
+    /* Don't free this, it's static. */
+    psr.msd.data = NULL;
+    psr.msd.length = 0;
+
     if (retval = krb5_c_encrypt_length(context, master_keyblock.enctype,
 				       scratch->length, &enclen)) {
 	krb5_free_data(context, scratch);
@@ -187,7 +171,7 @@
 	goto cleanup;
     }
     tmpdata.ciphertext.length = enclen;
-    sc.sam_track_id = tmpdata.ciphertext; /* So we know to free it. */
+    g_sc.sam_track_id = tmpdata.ciphertext; /* So we know to free it. */
 
     retval = krb5_c_encrypt(context, &master_keyblock,
 			    /* XXX */ 0, 0, scratch, &tmpdata);
@@ -195,27 +179,30 @@
     if (retval)
 	goto cleanup;
 
-    sc.sam_pk_for_sad.length = 0;
-    sc.sam_nonce = 0;
+    g_sc.sam_pk_for_sad.length = 0;
+    g_sc.sam_nonce = 0;
 
 #if 0
-    /* We don't calculate a checksum since it could be used to crack the SAD */
-    sc.sam_cksum.length = krb5_checksum_size(context, CKSUMTYPE_RSA_MD5_DES);
-    if ((sc.sam_cksum.contents = malloc(sc.sam_cksum.length)) == NULL) {
+    /* We don't calculate a checksum since it makes the password crackable */
+    g_sc.sam_cksum.length = krb5_checksum_size(context, CKSUMTYPE_RSA_MD5_DES);
+    if ((g_sc.sam_cksum.contents = malloc(g_sc.sam_cksum.length)) == NULL) {
 	return ENOMEM;
     }
 
     if (retval = krb5_calculate_checksum(context, CKSUMTYPE_RSA_MD5_DES,
-					 sc.sam_challenge.data,
-					 sc.sam_challenge.length,
+					 g_sc.sam_challenge.data,
+					 g_sc.sam_challenge.length,
 					 client_key.contents, /* key */
 					 client_key.length, /* key length */
-					 &sc.sam_cksum)) {
+					 &g_sc.sam_cksum)) {
 	goto cleanup;
     }
+#else /* 0 */
+    g_sc.sam_cksum.contents = NULL;
+    g_sc.sam_cksum.length = 0;
 #endif /* 0 */
       
-    if (retval = encode_krb5_sam_challenge(&sc, &scratch))
+    if (retval = encode_krb5_sam_challenge(&g_sc, &scratch))
 	goto cleanup;
 
     pa_data->magic = KV5M_PA_DATA;
@@ -235,112 +222,83 @@
     krb5_free_predicted_sam_response_contents(context, &psr);
 
     /* Don't use the abstraction to free sc; most of it is static. */
-    if (sc.sam_track_id.data);
-	krb5_xfree(sc.sam_track_id.data);
-    if (sc.sam_cksum.contents)
-	krb5_xfree(sc.sam_cksum.contents);
+    if (g_sc.sam_track_id.data)
+	krb5_xfree(g_sc.sam_track_id.data);
+    if (g_sc.sam_cksum.contents)
+	krb5_xfree(g_sc.sam_cksum.contents);
+
+    /* Reset global information for next customer. */
+    g_sc.sam_magic = 0;
+    g_sid_track_data.state = SECURID_STATE_INITIAL;
 
     return retval;
 
-#else /* SECURID && KRBCONF_KDC_MODIFIES_KDB */
+#else /* SECURID */
     return KRB5KDC_ERR_PREAUTH_FAILED;
-#endif /* SECURID && KRBCONF_KDC_MODIFIES_KDB */
+#endif /* SECURID */
 }
 
 
 /*
  * The new PIN/next PRN functions force passing in the enc_tkt_reply.
- * Because of this, we also have to keep per-user state somewhere,
- * the obvious place is the tl_data. This generates it's own problems.
  */
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-sam_verify_securid(context, request, assoc, npr, mode, sr, enc_tkt_reply,
-		   as_key)
+sam_verify_securid(context, request, client, assoc, npr, mode, sr,
+		   enc_tkt_reply, as_key)
     krb5_context	context;
     krb5_kdc_req *	request;
-    krb5_db_entry	assoc;
+    krb5_db_entry *	client;
+    krb5_db_entry *	assoc;
     int			npr;
     int			mode;
     krb5_sam_response *	sr;
     krb5_enc_tkt_part *	enc_tkt_reply;
     krb5_keyblock *	as_key;
 {
-#if defined(SECURID) && defined(KRBCONF_KDC_MODIFIES_KDB)
-    krb5_error_code			retval, retval2;
+#if defined(SECURID)
+    krb5_error_code			retval;
     krb5_data				scratch;
     krb5_enc_data			tmpdata;
-    krb5_tl_data			tl_data;
-    krb5_securid_state			securid_state;
-    krb5_int32				old_state;
+    krb5_keyblock			client_key;
 
     krb5_predicted_sam_response *	psr = 0;
     krb5_enc_sam_response_enc *		esre = 0;
     krb5_timestamp			timenow;
 
-    struct SD_CLIENT			sd_dat, *sd;
-    char				passcode[LENPRNST + 1];
     char *				user = 0, cp;
 
-    memset(&securid_state, 0, sizeof(securid_state));
-    securid_state.state = old_state = SECURID_STATE_INITIAL;
+    memset(&client_key, 0, sizeof(client_key));
+    memset(&g_sid_track_data.sd_info, 0, sizeof(g_sid_track_data.sd_info));
 
     /* Sanity check */
-    if (sr->sam_type != PA_SAM_TYPE_SECURID) {
+    if (sr->sam_track_id.length && (sr->sam_type != PA_SAM_TYPE_SECURID)) {
 	com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
 		"inconsistent sam_type (SecurID expected)");
 	goto cleanup;
     }
 
-    scratch.length = sr->sam_track_id.length;
+    scratch.length = sr->sam_enc_nonce_or_ts.ciphertext.length;
     if (!scratch.length) {
 	com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
-		"securid track_id data not found");
+		"SecurID sam_enc_nonce_or_ts not found");
 	goto cleanup;
     }
     if ((scratch.data = malloc(scratch.length)) == NULL) {
 	retval = ENOMEM;
 	goto cleanup;
     }
-
-    tmpdata.enctype = ENCTYPE_UNKNOWN;
-    tmpdata.ciphertext = sr->sam_track_id;
-    if (retval = krb5_c_decrypt(context, &master_keyblock, /* XXX */ 0, 0,
-				&tmpdata, &scratch)) {
-	/* Record our retval, but let the client see a generic error. */
-	com_err("krb5kdc", retval, "decrypt track_id failed");
-	retval = KRB5KDC_ERR_PREAUTH_FAILED;
-	krb5_xfree(scratch.data);
-	goto cleanup;
-    }
 
-    retval = decode_krb5_predicted_sam_response(&scratch, &psr);
-    krb5_xfree(scratch.data);
-    if (retval) {
-	com_err("krb5kdc", retval, "decode_krb5_predicted_sam_response failed");
-	goto cleanup;
-    }
-
-    if (psr->kdc_id != kdc_id) {
-	com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
-		"Warning - possible SAM replay attack!");
-	/* Reset state so user can try again quickly. */
-	old_state = SECURID_STATE_NONE;
-	goto update_tl_data;
-    }
-
-    scratch.length = sr->sam_enc_nonce_or_ts.ciphertext.length;
-    if (!scratch.length) {
-	com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
-		"SecurID sam_enc_nonce_or_ts not found");
+    /* Get the client_key ourself; we may not have a psr. */
+    if (retval = krb5_dbekd_decrypt_key_data(kdc_context, &master_encblock,
+					     client->key_data, &client_key,
+					     NULL)) {
+	com_err("krb5kdc", retval, "SecurID: cannot get client key");
 	goto cleanup;
     }
-    if ((scratch.data = malloc(scratch.length)) == NULL) {
-	retval = ENOMEM;
-	goto cleanup;
-    }
 
-    /* Now use psr->sam_key to verify */
-    if (retval = krb5_c_decrypt(context, &psr->sam_key, /* XXX */ 0, 0,
+    /* Now use client_key to verify the timestamp. */
+    client_key.enctype = sr->sam_enc_nonce_or_ts.enctype;
+    if (retval = krb5_c_decrypt(context, &client_key, /* XXX */ 0, 0,
 				&sr->sam_enc_nonce_or_ts, &scratch)) {
 	com_err("krb5kdc", retval, "decrypt nonce_or_ts failed");
 	retval = KRB5KDC_ERR_PREAUTH_FAILED;
@@ -367,14 +325,17 @@
 	goto cleanup;
     }
 
-    /* Success! Unlike most SAM types, we don't set the as_key. */
-
     /* Now verify the Passcode. */
+    if (!esre->sam_sad.length) {
+	com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
+		"SecurID: client did not supply SAD data");
+	goto cleanup;
+    }
+
     if (need_to_creadcfg) {
 	creadcfg();
 	need_to_creadcfg = 0;
     }
-    memset(&sd_dat, 0, sizeof(sd_dat));
 
     if (retval = krb5_unparse_name(context, request->client->princ, &user)) {
 	com_err("krb5kdc", retval, "Cannot unparse name for SecurID check");
@@ -383,41 +344,63 @@
     if (cp = strchr(user, '@'))
 	*cp = '\0';
 
-    /* What did the user return to us? */
-    tl_data.tl_data_type = KRB5_TL_SECURID_STATE;
-    if ((retval = krb5_dbe_lookup_tl_data(kdc_context, &assoc, &tl_data)) ||
-	(tl_data.tl_data_length == 0)) {
-	if (tl_data.tl_data_length != sizeof(securid_state)) {
+    scratch.length = sr->sam_track_id.length;
+    if (!scratch.length) {
+	/* Client knew he had to use time/event-based SAM. */
+	g_sid_track_data.state = SECURID_STATE_INITIAL;
+    } else {
+	if ((scratch.data = malloc(scratch.length)) == NULL) {
+	    retval = ENOMEM;
+	    goto cleanup;
+	}
+
+	tmpdata.enctype = ENCTYPE_UNKNOWN;
+	tmpdata.ciphertext = sr->sam_track_id;
+	if (retval = krb5_c_decrypt(context, &master_keyblock, /* XXX */ 0, 0,
+				    &tmpdata, &scratch)) {
+	    /* Record our retval, but let the client see a generic error. */
+	    com_err("krb5kdc", retval, "decrypt track_id failed");
+	    retval = KRB5KDC_ERR_PREAUTH_FAILED;
+	    krb5_xfree(scratch.data);
+	    goto cleanup;
+	}
+
+	retval = decode_krb5_predicted_sam_response(&scratch, &psr);
+	krb5_xfree(scratch.data);
+	if (retval) {
+	    com_err("krb5kdc", retval,
+		    "decode_krb5_predicted_sam_response failed");
+	    goto cleanup;
+	}
+
+	if (psr->kdc_id != kdc_id) {
 	    com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
-		    "corrupted tl_data!");
+		    "Warning - possible SAM replay attack!");
 	    goto cleanup;
 	}
-	memcpy(securid_state, tl_data.tl_data_contents, sizeof(securid_state));
-	old_state = securid_state.state;
 
-	/*
-	 * Verify that the tl_data is not stale (see comment in generate).
-	 * XXX By setting old_state we might introduce a condition where
-	 * user cannot login (if there is a problem with updating the db).
-	 */
-	if ((timenow - securid_state.tl_time) > 90) {
-	    memset(&securid_state, 0, sizeof(securid_state));
-	    securid_state.state = old_state = SECURID_STATE_INITIAL;
+	/* Sanity check */
+	if (psr->msd.length != sizeof(g_sid_track_data)) {
+	    com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
+		    "psr->msd (sid_track_data) is garbage");
+	    goto cleanup;
 	}
+	memcpy(&g_sid_track_data, psr->msd.data, psr->msd.length);
     }
 
-    switch (securid_state.state) {
+    switch (g_sid_track_data.state) {
     case SECURID_STATE_INITIAL:
 	if (esre->sam_sad.length > LENPRNST) {
-	    /* User entered too much data, keep same state. */
+	    /* User entered too much data. */
 	    retval = KRB5KDC_ERR_PREAUTH_FAILED;
 	    goto cleanup;
 	}
-	memcpy(&passcode, esre->sam_sad.data, esre->sam_sad.length);
-	passcode[esre->sam_sad.length] = '\0';
+	memcpy(&g_sid_track_data.passcode, esre->sam_sad.data,
+	       esre->sam_sad.length);
+	g_sid_track_data.passcode[esre->sam_sad.length] = '\0';
 
 	if (need_to_sd_init) {
-	    if (sd_init(&sd_dat)) {
+	    if (sd_init(&g_sid_track_data.sd_info)) {
 		com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
 			"Cannot initialize SecurID communications");
 		goto cleanup;
@@ -425,7 +408,8 @@
 	    need_to_sd_init = 0;
 	}
 
-	retval = sd_check(passcode, user, &sd_dat);
+	retval = sd_check(g_sid_track_data.passcode, user,
+			  &g_sid_track_data.sd_info);
 	switch (retval) {
 	case ACM_OK:
 	    setflag(enc_tkt_reply->flags, TKT_FLG_HW_AUTH);
@@ -447,8 +431,7 @@
 	     * a failure.
 	     */
 	    retval = 0;
-	    securid_state.state = SECURID_STATE_NEXT_CODE;
-	    securid_state.sd_info = sd_dat;
+	    g_sid_track_data.state = SECURID_STATE_NEXT_CODE;
 	    break;
 
 	case ACM_NEW_PIN_REQUIRED:
@@ -461,14 +444,13 @@
 	     * also, the prompt will be wrong.) Also, the PIN will
 	     * be visible when typed. :(
 	     */
-	    if (sd_dat.user_selectable == CANNOT_CHOOSE_PIN) {
+	    if (g_sid_track_data.sd_info.user_selectable == CANNOT_CHOOSE_PIN) {
 		com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
 			"SecurID new PIN needed but not user-selectable");
 		goto cleanup;
 	    }
 	    retval = 0;
-	    securid_state.state = SECURID_STATE_NEW_PIN;
-	    securid_state.sd_info = sd_dat;
+	    g_sid_track_data.state = SECURID_STATE_NEW_PIN;
 	    break;
 
 	default:
@@ -483,8 +465,7 @@
 	break;
 
     case SECURID_STATE_NEXT_CODE:
-	sd = &securid_state.sd_info;
-	retval = sd_next(passcode, sd);
+	retval = sd_next(g_sid_track_data.passcode, &g_sid_track_data.sd_info);
 	if (retval == ACM_OK) {
 	    setflag(enc_tkt_reply->flags, TKT_FLG_HW_AUTH);
 	    setflag(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH);
@@ -492,26 +473,35 @@
 	} else {
 	    retval = KRB5KDC_ERR_PREAUTH_FAILED;
 	}
-	securid_state.state = SECURID_STATE_INITIAL;
 	break;
 
     case SECURID_STATE_NEW_PIN:
-	/*
-	 * Store the user supplied PIN for verification.
-	 * Boundary checking has already been done.
-	 */
+	/* Save the PIN and ask for it again. */
+	if (esre->sam_sad.length > LENPRNST) {
+	    /* User entered too much data. */
+	    retval = KRB5KDC_ERR_PREAUTH_FAILED;
+	    goto cleanup;
+	}
+	memcpy(&g_sid_track_data.passcode, esre->sam_sad.data,
+	       esre->sam_sad.length);
+	g_sid_track_data.passcode[esre->sam_sad.length] = '\0';
+	g_sid_track_data.state = SECURID_STATE_NEW_PIN_AGAIN;
 	retval = 0;
-	strcpy(securid_state.newpin, passcode);
-	securid_state.state = SECURID_STATE_NEW_PIN_AGAIN;
 	break;
 
     case SECURID_STATE_NEW_PIN_AGAIN:
-	sd = &securid_state.sd_info;
 	/* Verify 2nd entry with the previous. */
-	if (strncmp(passcode, securid_state.newpin, LENPRNST) != 0) {
+	if (esre->sam_sad.length > LENPRNST) {
+	    /* User entered too much data. */
 	    retval = KRB5KDC_ERR_PREAUTH_FAILED;
+	    goto cleanup;
+	}
+	if (strncmp(g_sid_track_data.passcode, esre->sam_sad.data,
+		    LENPRNST) != 0) {
+	    retval = KRB5KDC_ERR_PREAUTH_FAILED;
 	} else {
-	    retval = sd_pin(passcode, '\0', sd);
+	    retval = sd_pin(g_sid_track_data.passcode, '\0',
+			    &g_sid_track_data.sd_info);
 	    if (retval == ACM_NEW_PIN_ACCEPTED) {
 		retval = 0;
 	    } else {
@@ -523,52 +513,30 @@
 
     default:
 	com_err("krb5kdc", retval = KRB5KDC_ERR_PREAUTH_FAILED,
-		"bad state in securid tl_data");
-	securid_state.state = SECURID_STATE_INITIAL;
+		"bad state in returned sid_track_data");
 	break;
     } /* switch (securid_state.state) */
 
-update_tl_data:
-    /*
-     * Update state information if it has changed.
-     * Unlike CRYPTOCard, we might need to fail if we can't update.
-     * XXX This might be bad when the databases sync properly.
-     */
-    if (old_state != securid_state.state) {
-	if (retval2 = krb5_timeofday(context, &securid_state.tl_time)) {
-	    com_err("krb5kdc", retval2, "updating tl_time");
-	    if (securid_state.state != SECURID_STATE_INITIAL)
-		retval = KRB5KDC_ERR_PREAUTH_FAILED;
-	    goto cleanup;
-	}
-	tl_data.tl_data_length = sizeof(securid_state);
-	tl_data.tl_data_contents = &securid_state;
-
-	if (retval2 = krb5_dbe_update_tl_data(kdc_context, &assoc, &tl_data)) {
-	    com_err("krb5kdc", retval2, "while updating SecurID tl_data");
-	    if (securid_state.state != SECURID_STATE_INITIAL)
-		retval = KRB5KDC_ERR_PREAUTH_FAILED;
-	    goto cleanup;
-	if (retval2 = krb5_db_put_principal(kdc_context, &assoc, &npr)) {
-	    com_err("krb5kdc", retval2, "while storing SecurID tl_data");
-	    if (securid_state.state != SECURID_STATE_INITIAL)
-		retval = KRB5KDC_ERR_PREAUTH_FAILED;
-	    goto cleanup;
-	}
-    }
-
 cleanup:
     if (psr)
 	krb5_free_predicted_sam_response(context, psr);
     if (esre) 
 	krb5_free_enc_sam_response_enc(context, esre);
+    if (client_key.contents)
+	krb5_free_keyblock_contents(context, &client_key);
 
     if (user)
 	krb5_xfree(user);
 
+    if (retval || isflagset(enc_tkt_reply->flags, TKT_FLG_HW_AUTH)) {
+	/* Don't leave bogus state around. */
+	g_sc.sam_magic = 0;
+	g_sid_track_data.state = SECURID_STATE_NONE;
+    }
+
     return retval;
 
-#else /* SECURID && KRBCONF_KDC_MODIFIES_KDB */
+#else /* SECURID */
     return KRB5KDC_ERR_PREAUTH_FAILED;
-#endif /* SECURID && KRBCONF_KDC_MODIFIES_KDB */
+#endif /* SECURID */
 }
Index: kdc/preauth/pa_sam_skey.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/kdc/preauth/pa_sam_skey.c,v
retrieving revision 1.1
diff -u -r1.1 pa_sam_skey.c
--- pa_sam_skey.c	1998/11/25 04:06:18	1.1
+++ pa_sam_skey.c	1998/12/01 02:00:06
@@ -39,7 +39,7 @@
 		  mode, pa_data)
     krb5_context 	context;
     krb5_kdc_req *	request;
-    krb5_db_entry	assoc;
+    krb5_db_entry *	assoc;
     int			npr;
     krb5_keyblock	sam_key;
     krb5_keyblock	client_key;
@@ -54,10 +54,12 @@
     
 
 KRB5_DLLIMP krb5_error_code KRB5_CALLCONV
-sam_verify_skey(context, request, assoc, npr, mode, sr, enc_tkt_reply, as_key)
+sam_verify_skey(context, request, client, assoc, npr, mode, sr,
+		enc_tkt_reply, as_key)
     krb5_context	context;
     krb5_kdc_req *	request;
-    krb5_db_entry	assoc;
+    krb5_db_entry *	client;
+    krb5_db_entry *	assoc;
     int			npr;
     int			mode;
     krb5_sam_response *	sr;
Index: lib/krb5/asn.1/asn1_k_decode.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/lib/krb5/asn.1/asn1_k_decode.c,v
retrieving revision 1.5
diff -u -r1.5 asn1_k_decode.c
--- asn1_k_decode.c	1998/11/25 22:35:55	1.5
+++ asn1_k_decode.c	1998/12/01 02:00:06
@@ -814,23 +814,9 @@
   { begin_structure();
     get_field(val->sam_key,0,asn1_decode_encryption_key);
     get_field(val->kdc_id,1,asn1_decode_int32);
+    opt_string(val->msd,2,asn1_decode_generalstring);
     end_structure();
     val->magic = KV5M_PREDICTED_SAM_RESPONSE;
-  }
-  cleanup();
-}
-
-asn1_error_code asn1_decode_rb1_track_data(buf, val)
-     asn1buf * buf;
-     krb5_rb1_track_data * val;
-{
-  setup();
-  { begin_structure();
-    opt_string(val->next_challenge, 0, asn1_decode_charstring);
-    get_field(val->sam_key, 1, asn1_decode_encryption_key);
-    get_field(val->kdc_id,2,asn1_decode_int32);
-    end_structure();
-    val->magic = KV5M_RB1_TRACK_DATA;
   }
   cleanup();
 }
Index: lib/krb5/asn.1/asn1_k_decode.h
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/lib/krb5/asn.1/asn1_k_decode.h,v
retrieving revision 1.2
diff -u -r1.2 asn1_k_decode.h
--- asn1_k_decode.h	1998/11/25 06:50:49	1.2
+++ asn1_k_decode.h	1998/12/01 02:00:06
@@ -148,8 +148,6 @@
 	PROTOTYPE((asn1buf *buf, krb5_sam_response *val));
 asn1_error_code asn1_decode_predicted_sam_response
 	PROTOTYPE((asn1buf *buf, krb5_predicted_sam_response *val));
-asn1_error_code asn1_decode_rb1_track_data
-	PROTOTYPE((asn1buf *buf, krb5_rb1_track_data *val));
 
 /* arrays */
 asn1_error_code asn1_decode_authorization_data
Index: lib/krb5/asn.1/asn1_k_encode.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/lib/krb5/asn.1/asn1_k_encode.c,v
retrieving revision 1.5
diff -u -r1.5 asn1_k_encode.c
--- asn1_k_encode.c	1998/11/25 22:35:56	1.5
+++ asn1_k_encode.c	1998/12/01 02:00:07
@@ -949,24 +949,12 @@
 {
   asn1_setup();
 
+  add_optstring(val->msd,2,asn1_encode_generalstring);
   asn1_addfield(val->kdc_id,1,asn1_encode_integer);
   asn1_addfield(&(val->sam_key),0,asn1_encode_encryption_key);
 
   asn1_makeseq();
 
   asn1_cleanup();
-}
-
-asn1_error_code asn1_encode_rb1_track_data(buf, val, retlen)
-    asn1buf * buf;
-    const krb5_rb1_track_data *val;
-    int *retlen;
-{
-    asn1_setup();
-    asn1_addfield(val->kdc_id,2,asn1_encode_integer);
-    asn1_addfield(&(val->sam_key), 1, asn1_encode_encryption_key);
-    add_optstring(val->next_challenge, 0, asn1_encode_charstring);
-    asn1_makeseq();
-    asn1_cleanup();
 }
 
Index: lib/krb5/asn.1/asn1_k_encode.h
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/lib/krb5/asn.1/asn1_k_encode.h,v
retrieving revision 1.2
diff -u -r1.2 asn1_k_encode.h
--- asn1_k_encode.h	1998/11/25 06:50:49	1.2
+++ asn1_k_encode.h	1998/12/01 02:00:07
@@ -245,8 +245,4 @@
 	PROTOTYPE((asn1buf *buf, const krb5_predicted_sam_response *val, 
 		   int *retlen));
 
-asn1_error_code asn1_encode_rb1_track_data
-	PROTOTYPE((asn1buf *buf, const krb5_rb1_track_data *val, 
-		   int *retlen));
-
 #endif
Index: lib/krb5/asn.1/krb5_decode.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/lib/krb5/asn.1/krb5_decode.c,v
retrieving revision 1.2
diff -u -r1.2 krb5_decode.c
--- krb5_decode.c	1998/11/25 06:50:49	1.2
+++ krb5_decode.c	1998/12/01 02:00:07
@@ -836,17 +836,3 @@
 
   cleanup(free);
 }
-
-krb5_error_code decode_krb5_rb1_track_data(code, rep)
-     const krb5_data * code;
-     krb5_rb1_track_data **rep;
-{
-  setup_buf_only();		/* preallocated */
-  alloc_field(*rep,krb5_rb1_track_data);
-
-  retval = asn1_decode_rb1_track_data(&buf,*rep);
-  if(retval) clean_return(retval);
-
-  cleanup(free);
-}
-
Index: lib/krb5/asn.1/krb5_encode.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/lib/krb5/asn.1/krb5_encode.c,v
retrieving revision 1.2
diff -u -r1.2 krb5_encode.c
--- krb5_encode.c	1998/11/25 06:50:49	1.2
+++ krb5_encode.c	1998/12/01 02:00:07
@@ -847,14 +847,3 @@
   sum += length;
   krb5_cleanup();
 }
-
-krb5_error_code encode_krb5_rb1_track_data(rep, code)
-     const krb5_rb1_track_data * rep;
-     krb5_data ** code;
-{
-  krb5_setup();
-  retval = asn1_encode_rb1_track_data(buf,rep,&length);
-  if(retval) return retval;
-  sum += length;
-  krb5_cleanup();
-}
Index: lib/krb5/krb/kfree.c
===================================================================
RCS file: /icon/d04/cvsroot/3rd-party/krb5-19981119/lib/krb5/krb/kfree.c,v
retrieving revision 1.3
diff -u -r1.3 kfree.c
--- kfree.c	1998/11/25 23:47:44	1.3
+++ kfree.c	1998/12/01 02:00:07
@@ -651,8 +651,10 @@
 {
     if (!psr)
 	return;
-    if (psr->sam_key.contents);
+    if (psr->sam_key.contents)
 	krb5_free_keyblock_contents(ctx, &psr->sam_key);
+    if (psr->msd.data)
+	krb5_free_data_contents(ctx, &psr->msd);
 }
 
 KRB5_DLLIMP void KRB5_CALLCONV
@@ -673,28 +675,6 @@
 	return;
     if (esre->sam_sad.data)
 	krb5_free_data_contents(ctx, &esre->sam_sad);
-}
-
-KRB5_DLLIMP void KRB5_CALLCONV
-krb5_free_rb1_track_data(krb5_context ctx, krb5_rb1_track_data FAR *rb1td)
-{
-    if (!rb1td)
-	return
-    krb5_free_rb1_track_data_contents(ctx, rb1td);
-    krb5_xfree(rb1td);
-}
-
-
-KRB5_DLLIMP void KRB5_CALLCONV
-krb5_free_rb1_track_data_contents(krb5_context ctx,
-				  krb5_rb1_track_data FAR *rb1td)
-{
-    if (!rb1td)
-	return;
-    if (rb1td->sam_key.contents)
-	krb5_free_keyblock_contents(ctx, &rb1td->sam_key);
-    if (rb1td->next_challenge.data)
-	krb5_free_data_contents(ctx, &rb1td->next_challenge);
 }
 
 
>Audit-Trail:
>Unformatted:

home help back first fref pref prev next nref lref last post