[1317] in Kerberos_V5_Development

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

Audit GSS-API changes

daemon@ATHENA.MIT.EDU (Barry Jaspan)
Fri Jun 14 14:27:10 1996

Date: Fri, 14 Jun 96 14:26:56 -0400
From: "Barry Jaspan" <bjaspan@MIT.EDU>
To: marc@MIT.EDU, krbdev@MIT.EDU


Enclosed below are my first-pass patches at updating the GSS-API to
understand the new oid and use the right IV for checksums.  The
patches are pretty straightforward, but I've never touched the gss-api
code before so I'd like people to audit them.  The patches are again
OV_9510_INTEGRATION (branch: 1.28.2), and the working files are in
/marc/src/lib/gssapi on beeblebrox.

The patches arrange for the server to understand the old and new oid
and behave accordingly.  This means old and new clients can talk to a
new server, but new clients cannot talk to an old server unless the
application protocol contains some versioning mechanism.

Barry

Index: accept_sec_context.c
===================================================================
RCS file: /mit/krb5/.cvsroot/src/lib/gssapi/krb5/accept_sec_context.c,v
retrieving revision 1.28.2.3
diff -c -r1.28.2.3 accept_sec_context.c
*** accept_sec_context.c	1996/04/20 04:04:37	1.28.2.3
--- accept_sec_context.c	1996/06/14 17:14:09
***************
*** 86,153 ****
      return retval;
  }
  
- #if 0
- 
- static krb5_error_code
- make_ap_rep(krb5_tkt_authent *authdat,
- 	    krb5_keyblock *session_key,
- 	    krb5_int32 *seq_send,
- 	    gss_buffer_t token)
- {
-    krb5_error_code code;
-    krb5_ap_rep_enc_part ap_rep_data;
-    krb5_data ap_rep;
-    int tlen;
-    unsigned char *t, *ptr;
- 
-    /* make the ap_rep */
- 
-    ap_rep_data.ctime = authdat->authenticator->ctime;
-    ap_rep_data.cusec = authdat->authenticator->cusec;
-    ap_rep_data.subkey = authdat->authenticator->subkey;
- 
-    if (code = krb5_generate_seq_number(authdat->ticket->enc_part2->session,
- 				       &ap_rep_data.seq_number))
-       return(code);
- 
-    if (code = krb5_mk_rep(&ap_rep_data, session_key, &ap_rep))
-       return(code);
- 
-    /* build up the token */
- 
-    /* allocate space for the token */
-    tlen = g_token_size(gss_mech_krb5, ap_rep.length);
- 
-    if ((t = (unsigned char *) xmalloc(tlen)) == NULL) {
-       xfree(ap_rep.data);
-       return(ENOMEM);
-    }
- 
-    /* fill in the buffer */
- 
-    ptr = t;
- 
-    g_make_token_header(gss_mech_krb5, ap_rep.length,
- 		       &ptr, KG_TOK_CTX_AP_REP);
- 
-    TWRITE_STR(ptr, ap_rep.data, ap_rep.length);
- 
-    /* free the ap_rep */
- 
-    xfree(ap_rep.data);
- 
-    /* pass everything back */
- 
-    *seq_send = ap_rep_data.seq_number;
- 
-    token->length = tlen;
-    token->value = (void *) t;
- 
-    return(0);
- }
- 
- #endif
- 
  OM_uint32
  krb5_gss_accept_sec_context(minor_status, context_handle, 
  			    verifier_cred_handle, input_token,
--- 86,91 ----
***************
*** 190,195 ****
--- 128,134 ----
     int option_id;
     krb5_data option;
     krb5_auth_context auth_context_cred = NULL;
+    const gss_OID_desc *mech_used = NULL;
  
  
     if (GSS_ERROR(kg_get_context(minor_status, &context)))
***************
*** 245,253 ****
     if (err = g_verify_token_header((gss_OID) gss_mech_krb5, &(ap_req.length),
  				   &ptr, KG_TOK_CTX_AP_REQ,
  				   input_token->length)) {
!       *minor_status = err;
!       return(GSS_S_DEFECTIVE_TOKEN);
!    }
  
     sptr = (char *) ptr;
     TREAD_STR(sptr, ap_req.data, ap_req.length);
--- 184,207 ----
     if (err = g_verify_token_header((gss_OID) gss_mech_krb5, &(ap_req.length),
  				   &ptr, KG_TOK_CTX_AP_REQ,
  				   input_token->length)) {
! 	/*
! 	 * Previous versions of this library used the old mech_id
! 	 * and some broken behavior (wrong IV on checksum
! 	 * encryption).  We support the old mech_id for
! 	 * compatibility, and use it to decide when to use the
! 	 * old behavior.
! 	 */
! 	if (err != G_WRONG_MECH ||
! 	    (err = g_verify_token_header((gss_OID) gss_mech_krb5_old,
! 					 &(ap_req.length), 
! 					 &ptr, KG_TOK_CTX_AP_REQ,
! 					 input_token->length))) {
! 	     *minor_status = err;
! 	     return(GSS_S_DEFECTIVE_TOKEN);
! 	} else
! 	     mech_used = gss_mech_krb5_old;
!    } else
! 	mech_used = gss_mech_krb5;
  
     sptr = (char *) ptr;
     TREAD_STR(sptr, ap_req.data, ap_req.length);
***************
*** 414,419 ****
--- 368,374 ----
     }
  
     memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec));
+    ctx->mech_used = mech_used;
     ctx->auth_context = auth_context;
     ctx->initiate = 0;
     ctx->mutual = gss_flags & GSS_C_MUTUAL_FLAG;
***************
*** 505,511 ****
  	 return(GSS_S_FAILURE);
        }
        krb5_auth_con_getlocalseqnumber(context, auth_context, &ctx->seq_send);
!       token.length = g_token_size((gss_OID) gss_mech_krb5, ap_rep.length);
  
        if ((token.value = (unsigned char *) xmalloc(token.length)) == NULL) {
  	 (void)krb5_gss_delete_sec_context(minor_status, 
--- 460,466 ----
  	 return(GSS_S_FAILURE);
        }
        krb5_auth_con_getlocalseqnumber(context, auth_context, &ctx->seq_send);
!       token.length = g_token_size((gss_OID) mech_used, ap_rep.length);
  
        if ((token.value = (unsigned char *) xmalloc(token.length)) == NULL) {
  	 (void)krb5_gss_delete_sec_context(minor_status, 
***************
*** 514,520 ****
  	 return(GSS_S_FAILURE);
        }
        ptr = token.value;
!       g_make_token_header((gss_OID) gss_mech_krb5, ap_rep.length,
  			  &ptr, KG_TOK_CTX_AP_REP);
  
        TWRITE_STR(ptr, ap_rep.data, ap_rep.length);
--- 469,475 ----
  	 return(GSS_S_FAILURE);
        }
        ptr = token.value;
!       g_make_token_header((gss_OID) mech_used, ap_rep.length,
  			  &ptr, KG_TOK_CTX_AP_REP);
  
        TWRITE_STR(ptr, ap_rep.data, ap_rep.length);
***************
*** 542,548 ****
     }
  
     if (mech_type)
!       *mech_type = (gss_OID) gss_mech_krb5;
  
     if (time_rec) {
        if ((code = krb5_timeofday(context, &now))) {
--- 497,503 ----
     }
  
     if (mech_type)
!       *mech_type = (gss_OID) mech_used;
  
     if (time_rec) {
        if ((code = krb5_timeofday(context, &now))) {
Index: gssapiP_krb5.h
===================================================================
RCS file: /mit/krb5/.cvsroot/src/lib/gssapi/krb5/gssapiP_krb5.h,v
retrieving revision 1.27.2.3
diff -c -r1.27.2.3 gssapiP_krb5.h
*** gssapiP_krb5.h	1996/04/20 04:04:41	1.27.2.3
--- gssapiP_krb5.h	1996/06/14 17:13:28
***************
*** 113,118 ****
--- 113,119 ----
     int established;
     int big_endian;
     krb5_auth_context auth_context;
+    const gss_OID_desc *mech_used;
  } krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t;
  
  extern void *kg_vdb;
Index: gssapi_krb5.c
===================================================================
RCS file: /mit/krb5/.cvsroot/src/lib/gssapi/krb5/gssapi_krb5.c,v
retrieving revision 1.12.2.2
diff -c -r1.12.2.2 gssapi_krb5.c
*** gssapi_krb5.c	1996/04/18 01:39:08	1.12.2.2
--- gssapi_krb5.c	1996/06/14 16:27:45
***************
*** 49,56 ****
  /*
   * Encoding rules: The first two values are encoded in one byte as 40
   * * value1 + value2.  Subsequent values are encoded base 128, most
!  * significant digit first, with the high bit set on all octets except
!  * the last in each value's encoding.
   */
  
  static const gss_OID_desc oids[] = {
--- 49,56 ----
  /*
   * Encoding rules: The first two values are encoded in one byte as 40
   * * value1 + value2.  Subsequent values are encoded base 128, most
!  * significant digit first, with the high bit (\200) set on all octets
!  * except the last in each value's encoding.
   */
  
  static const gss_OID_desc oids[] = {
***************
*** 61,70 ****
     {9, "\052\206\110\206\367\022\001\002\002"},
  };
  
! const gss_OID_desc * const gss_mech_krb5 = oids+0;
  const gss_OID_desc * const gss_nt_krb5_name = oids+1;
  const gss_OID_desc * const gss_nt_krb5_principal = oids+2;
! const gss_OID_desc * const gss_new_mech_krb5 = oids+3;
  
  static const gss_OID_set_desc oidsets[] = {
     {1, (gss_OID) oids},
--- 61,70 ----
     {9, "\052\206\110\206\367\022\001\002\002"},
  };
  
! const gss_OID_desc * const gss_mech_krb5_old = oids+0;
  const gss_OID_desc * const gss_nt_krb5_name = oids+1;
  const gss_OID_desc * const gss_nt_krb5_principal = oids+2;
! const gss_OID_desc * const gss_mech_krb5 = oids+3;
  
  static const gss_OID_set_desc oidsets[] = {
     {1, (gss_OID) oids},
Index: gssapi_krb5.h
===================================================================
RCS file: /mit/krb5/.cvsroot/src/lib/gssapi/krb5/gssapi_krb5.h,v
retrieving revision 1.9.6.2
diff -c -r1.9.6.2 gssapi_krb5.h
*** gssapi_krb5.h	1996/04/18 01:39:10	1.9.6.2
--- gssapi_krb5.h	1996/06/14 17:15:13
***************
*** 31,36 ****
--- 31,37 ----
  #include <krb5.h>
  
  extern const gss_OID_desc * const gss_mech_krb5;
+ extern const gss_OID_desc * const gss_mech_krb5_old;
  extern const gss_OID_set_desc * const gss_mech_set_krb5;
  
  extern const gss_OID_desc * const gss_nt_krb5_name;
Index: init_sec_context.c
===================================================================
RCS file: /mit/krb5/.cvsroot/src/lib/gssapi/krb5/init_sec_context.c,v
retrieving revision 1.31.2.3
diff -c -r1.31.2.3 init_sec_context.c
*** init_sec_context.c	1996/04/20 04:04:45	1.31.2.3
--- init_sec_context.c	1996/06/14 16:37:41
***************
*** 302,307 ****
--- 302,308 ----
  
        /* fill in the ctx */
        memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec));
+       ctx->mech_used = gss_mech_krb5;
        ctx->auth_context = NULL;
        ctx->initiate = 1;
        ctx->mutual = req_flags & GSS_C_MUTUAL_FLAG;
Index: inq_context.c
===================================================================
RCS file: /mit/krb5/.cvsroot/src/lib/gssapi/krb5/inq_context.c,v
retrieving revision 1.7.2.1
diff -c -r1.7.2.1 inq_context.c
*** inq_context.c	1996/04/18 01:39:18	1.7.2.1
--- inq_context.c	1996/06/14 16:40:07
***************
*** 118,124 ****
        *lifetime_rec = lifetime;
  
     if (mech_type)
!       *mech_type = (gss_OID) gss_mech_krb5;
  
     if (ret_flags)
        *ret_flags = GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | ctx->mutual;
--- 118,124 ----
        *lifetime_rec = lifetime;
  
     if (mech_type)
!       *mech_type = (gss_OID) ctx->mech_used;
  
     if (ret_flags)
        *ret_flags = GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | ctx->mutual;
Index: inq_names.c
===================================================================
RCS file: /mit/krb5/.cvsroot/src/lib/gssapi/krb5/inq_names.c,v
retrieving revision 1.2.6.1
diff -c -r1.2.6.1 inq_names.c
*** inq_names.c	1996/04/18 01:39:21	1.2.6.1
--- inq_names.c	1996/06/14 16:41:01
***************
*** 43,49 ****
       * We only know how to handle our own mechanism.
       */
      if ((mechanism != GSS_C_NULL_OID) &&
! 	!g_OID_equal(gss_mech_krb5, mechanism)) {
  	*minor_status = 0;
  	return(GSS_S_FAILURE);
      }
--- 43,50 ----
       * We only know how to handle our own mechanism.
       */
      if ((mechanism != GSS_C_NULL_OID) &&
! 	!g_OID_equal(gss_mech_krb5, mechanism) &&
! 	!g_OID_equal(gss_mech_krb5_old, mechanism)) {
  	*minor_status = 0;
  	return(GSS_S_FAILURE);
      }
Index: k5seal.c
===================================================================
RCS file: /mit/krb5/.cvsroot/src/lib/gssapi/krb5/k5seal.c,v
retrieving revision 1.15.6.3
diff -c -r1.15.6.3 k5seal.c
*** k5seal.c	1996/04/20 04:04:47	1.15.6.3
--- k5seal.c	1996/06/14 17:15:43
***************
*** 24,30 ****
  
  static krb5_error_code
  make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
! 		signalg, cksum_size, sealalg, encrypt, toktype, bigend)
       krb5_context context;
       krb5_gss_enc_desc *enc_ed;
       krb5_gss_enc_desc *seq_ed;
--- 24,31 ----
  
  static krb5_error_code
  make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
! 		signalg, cksum_size, sealalg, encrypt, toktype,
! 		bigend, oid)
       krb5_context context;
       krb5_gss_enc_desc *enc_ed;
       krb5_gss_enc_desc *seq_ed;
***************
*** 38,43 ****
--- 39,45 ----
       int encrypt;
       int toktype;
       int bigend;
+      gss_OID oid;
  {
     krb5_error_code code;
     char *data_ptr;
***************
*** 60,66 ****
        tmsglen = 0;
     }
  
!    tlen = g_token_size((gss_OID) gss_mech_krb5, 14+cksum_size+tmsglen);
  
     if ((t = (unsigned char *) xmalloc(tlen)) == NULL)
        return(ENOMEM);
--- 62,68 ----
        tmsglen = 0;
     }
  
!    tlen = g_token_size((gss_OID) oid, 14+cksum_size+tmsglen);
  
     if ((t = (unsigned char *) xmalloc(tlen)) == NULL)
        return(ENOMEM);
***************
*** 69,76 ****
  
     ptr = t;
  
!    g_make_token_header((gss_OID) gss_mech_krb5,
! 		       14+cksum_size+tmsglen, &ptr, toktype);
  
     /* 0..1 SIGN_ALG */
  
--- 71,77 ----
  
     ptr = t;
  
!    g_make_token_header((gss_OID) oid, 14+cksum_size+tmsglen, &ptr, toktype);
  
     /* 0..1 SIGN_ALG */
  
***************
*** 233,239 ****
  
         xfree(cksum.contents);
  #else
!        if (code = kg_encrypt(context, seq_ed, NULL,
  			     md5cksum.contents, md5cksum.contents, 16)) {
  	  xfree(md5cksum.contents);
  	  xfree(t);
--- 234,242 ----
  
         xfree(cksum.contents);
  #else
!        if (code = kg_encrypt(context, seq_ed,
! 			     (oid == gss_mech_krb5_old ?
! 			      seq_ed->key->contents : NULL),
  			     md5cksum.contents, md5cksum.contents, 16)) {
  	  xfree(md5cksum.contents);
  	  xfree(t);
***************
*** 320,326 ****
  			      &ctx->seq_send, ctx->initiate,
  			      input_message_buffer, output_message_buffer,
  			      ctx->signalg, ctx->cksum_size, ctx->sealalg,
! 			      conf_req_flag, toktype, ctx->big_endian)) {
        *minor_status = code;
        return(GSS_S_FAILURE);
     }
--- 323,330 ----
  			      &ctx->seq_send, ctx->initiate,
  			      input_message_buffer, output_message_buffer,
  			      ctx->signalg, ctx->cksum_size, ctx->sealalg,
! 			      conf_req_flag, toktype, ctx->big_endian,
! 			      ctx->mech_used)) {
        *minor_status = code;
        return(GSS_S_FAILURE);
     }
Index: k5unseal.c
===================================================================
RCS file: /mit/krb5/.cvsroot/src/lib/gssapi/krb5/k5unseal.c,v
retrieving revision 1.13.6.3
diff -c -r1.13.6.3 k5unseal.c
*** k5unseal.c	1996/04/20 04:04:49	1.13.6.3
--- k5unseal.c	1996/06/14 17:16:06
***************
*** 89,95 ****
  
     ptr = (unsigned char *) input_token_buffer->value;
  
!    if (err = g_verify_token_header((gss_OID) gss_mech_krb5, &bodysize,
  				   &ptr, toktype,
  				   input_token_buffer->length)) {
        *minor_status = err;
--- 89,95 ----
  
     ptr = (unsigned char *) input_token_buffer->value;
  
!    if (err = g_verify_token_header((gss_OID) ctx->mech_used, &bodysize,
  				   &ptr, toktype,
  				   input_token_buffer->length)) {
        *minor_status = err;
***************
*** 285,291 ****
  
        xfree(cksum.contents);
  #else
!       if (code = kg_encrypt(context, &ctx->seq, NULL,
  			    md5cksum.contents, md5cksum.contents, 16)) {
  	 xfree(md5cksum.contents);
  	 if (toktype == KG_TOK_SEAL_MSG)
--- 285,293 ----
  
        xfree(cksum.contents);
  #else
!       if (code = kg_encrypt(context, &ctx->seq,
! 			    (ctx->mech_used == gss_mech_krb5 ?
! 			     NULL : ctx->seq.key->contents),
  			    md5cksum.contents, md5cksum.contents, 16)) {
  	 xfree(md5cksum.contents);
  	 if (toktype == KG_TOK_SEAL_MSG)
Index: rel_oid.c
===================================================================
RCS file: /mit/krb5/.cvsroot/src/lib/gssapi/krb5/rel_oid.c,v
retrieving revision 1.4
diff -c -r1.4 rel_oid.c
*** rel_oid.c	1996/03/21 04:39:12	1.4
--- rel_oid.c	1996/06/14 16:33:51
***************
*** 73,78 ****
--- 73,79 ----
       */
     
      if ((*oid != gss_mech_krb5) &&
+ 	(*oid != gss_mech_krb5_old) &&
  	(*oid != gss_nt_krb5_name) &&
  	(*oid != gss_nt_krb5_principal)) {
  	/* We don't know about this OID */
Index: ser_sctx.c
===================================================================
RCS file: /mit/krb5/.cvsroot/src/lib/gssapi/krb5/ser_sctx.c,v
retrieving revision 1.3.6.3
diff -c -r1.3.6.3 ser_sctx.c
*** ser_sctx.c	1996/04/20 04:04:52	1.3.6.3
--- ser_sctx.c	1996/06/14 17:17:45
***************
*** 255,265 ****
       *	krb5_int32	for established.
       *	krb5_int32	for big_endian.
       *	krb5_int32	for trailer.
       */
      kret = EINVAL;
      if ((ctx = (krb5_gss_ctx_id_rec *) arg)) {
! 	required = 14*sizeof(krb5_int32);
  	required += sizeof(ctx->seed);
  
  	kret = 0;
  	if (!kret && ctx->here)
--- 255,268 ----
       *	krb5_int32	for established.
       *	krb5_int32	for big_endian.
       *	krb5_int32	for trailer.
+      *  OM_uint32	for length of mech_used
+      *  length(mech_used) for mech_used
       */
      kret = EINVAL;
      if ((ctx = (krb5_gss_ctx_id_rec *) arg)) {
! 	required = 15*sizeof(krb5_int32);
  	required += sizeof(ctx->seed);
+ 	required += ctx->mech_used->length;
  
  	kret = 0;
  	if (!kret && ctx->here)
***************
*** 296,301 ****
--- 299,338 ----
      return(kret);
  }
  
+ static krb5_error_code kg_oid_externalize(kcontext, arg, buffer, lenremain)
+     krb5_context	kcontext;
+     krb5_pointer	arg;
+     krb5_octet		**buffer;
+     size_t		*lenremain;
+ {
+      gss_OID oid = (gss_OID) arg;
+      
+      (void) krb5_ser_pack_int32((krb5_int32) oid->length,
+ 				buffer, lenremain);
+      (void) krb5_ser_pack_bytes((krb5_octet *) oid->elements,
+ 				oid->length, buffer, lenremain);
+ }
+ 
+ static krb5_error_code
+ kg_oid_internalize(kcontext, argp, buffer, lenremain)
+     krb5_context	kcontext;
+     krb5_pointer	*argp;
+     krb5_octet		**buffer;
+     size_t		*lenremain;
+ {
+      gss_OID oid;
+      krb5_int32 ibuf;
+ 
+      oid = (gss_OID) malloc(sizeof(gss_OID_desc));
+      if (oid == NULL)
+ 	  return ENOMEM;
+      (void) krb5_ser_unpack_int32(&ibuf, buffer, lenremain);
+      oid->length = ibuf;
+      (void) krb5_ser_unpack_bytes((krb5_octet *) oid->elements,
+ 				  oid->length, buffer, lenremain);
+      return 0;
+ }
+ 
  /*
   * Externalize this krb5_gss_ctx_id_ret.
   */
***************
*** 355,360 ****
--- 392,401 ----
  	    /* Now dynamic data */
  	    kret = 0;
  
+ 	    if (!kret && ctx->mech_used)
+ 		 kret = kg_oid_externalize(kcontext, ctx->mech_used,
+ 					   &bp, &remain); 
+ 	    
  	    if (!kret && ctx->here)
  		kret = krb5_externalize_opaque(kcontext,
  					       KV5M_PRINCIPAL,
***************
*** 452,457 ****
--- 493,503 ----
  	    (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
  	    ctx->big_endian = (int) ibuf;
  
+ 	    if ((kret = kg_oid_internalize(kcontext, &ctx->mech_used, &bp,
+ 					   &remain))) {
+ 		 if (kret == EINVAL)
+ 		      kret = 0;
+ 	    }
  	    /* Now get substructure data */
  	    if ((kret = krb5_internalize_opaque(kcontext,
  						KV5M_PRINCIPAL,
Index: wrap_size_limit.c
===================================================================
RCS file: /mit/krb5/.cvsroot/src/lib/gssapi/krb5/Attic/wrap_size_limit.c,v
rcsdiff: /mit/krb5/.cvsroot/src/lib/gssapi/krb5/Attic/wrap_size_limit.c,v: warning: Unknown phrases like `dead ...;' are present.
retrieving revision 1.1.2.2
diff -c -r1.1.2.2 wrap_size_limit.c
*** wrap_size_limit.c	1996/04/20 04:04:54	1.1.2.2
--- wrap_size_limit.c	1996/06/14 16:42:37
***************
*** 65,71 ****
  
      /* Calculate the token size and subtract that from the output size */
      cfsize = (conf_req_flag) ? kg_confounder_size(&ctx->enc) : 0;
!     ohlen = g_token_size((gss_OID) gss_mech_krb5,
  			 (unsigned int) cfsize + ctx->cksum_size + 14);
  
      /* Cannot have trailer length that will cause us to pad over our length */
--- 65,71 ----
  
      /* Calculate the token size and subtract that from the output size */
      cfsize = (conf_req_flag) ? kg_confounder_size(&ctx->enc) : 0;
!     ohlen = g_token_size((gss_OID) ctx->mech_used,
  			 (unsigned int) cfsize + ctx->cksum_size + 14);
  
      /* Cannot have trailer length that will cause us to pad over our length */



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