[1317] in Kerberos_V5_Development
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 */