[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#776981: unblock: krb5/1.12.1+dfsg-17



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package krb5

This version includes the upstream official patch for
mitkrb5-sa-2015-001, a series of security vulnerabilities made public
today.  I've received permission from the security team to upload a
backport of this patch to stable-security.

diff --git a/debian/.git-dpm b/debian/.git-dpm
index 423df28..237c3b1 100644
--- a/debian/.git-dpm
+++ b/debian/.git-dpm
@@ -1,6 +1,6 @@
 # see git-dpm(1) from git-dpm package
-877ad027ca2103f3ac2f581451fdd347a76b8981
-877ad027ca2103f3ac2f581451fdd347a76b8981
+769a3f26c919339002ef2936592a90d144d0e238
+769a3f26c919339002ef2936592a90d144d0e238
 00dec38e79dd6436e9efed873df00e6ea11fdd0e
 00dec38e79dd6436e9efed873df00e6ea11fdd0e
 krb5_1.12.1+dfsg.orig.tar.gz
diff --git a/debian/changelog b/debian/changelog
index 226cc36..c8a284c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,14 @@
+krb5 (1.12.1+dfsg-17) unstable; urgency=high
+
+  * MITKRB5-SA-2015-001
+    - CVE-2014-5352: gss_process_context_token() incorrectly frees context
+    - CVE-2014-9421: kadmind doubly frees partial deserialization results
+    - CVE-2014-9422: kadmind incorrectly validates server principal name  
+      - CVE-2014-9423: libgssrpc server applications leak uninitialized bytes
+
+
+ -- Sam Hartman <hartmans@debian.org>  Tue, 03 Feb 2015 10:29:35 -0500
+
 krb5 (1.12.1+dfsg-16) unstable; urgency=medium
 
   * Import upstream patches for CVE-2014-5353 and CVE-2014-5354,
diff --git a/debian/patches/series b/debian/patches/series
index 9d19440..721cb89 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -26,3 +26,4 @@ upstream/0025-Fix-build-on-systems-without-RTM_OLD.patch
 upstream/0026-Remove-rtm_type_name.patch
 upstream/0027-Fix-LDAP-misused-policy-name-crash-CVE-2014-5353.patch
 0028-Support-keyless-principals-in-LDAP-CVE-2014-5354.patch
+upstream/0029-MITKRB5-SA-2015-0001.patch
diff --git a/debian/patches/upstream/0029-MITKRB5-SA-2015-0001.patch b/debian/patches/upstream/0029-MITKRB5-SA-2015-0001.patch
new file mode 100644
index 0000000..c8183a3
--- /dev/null
+++ b/debian/patches/upstream/0029-MITKRB5-SA-2015-0001.patch
@@ -0,0 +1,397 @@
+From 769a3f26c919339002ef2936592a90d144d0e238 Mon Sep 17 00:00:00 2001
+From: Sam Hartman <hartmans@debian.org>
+Date: Tue, 3 Feb 2015 10:26:16 -0500
+Subject: MITKRB5-SA-2015-0001
+
+Topic: Vulnerabilities in kadmind, libgssrpc, gss_process_context_token
+
+CVE-2014-5352: gss_process_context_token() incorrectly frees context
+
+CVSSv2 Vector: AV:N/AC:L/Au:S/C:C/I:C/A:C/E:POC/RL:OF/RC:C
+
+CVSSv2 Base Score:      9.0
+
+Access Vector:          Network
+Access Complexity:      Low
+Authentication:         Single
+Confidentiality Impact: Complete
+Integrity Impact:       Complete
+Availability Impact:    Complete
+
+CVSSv2 Temporal Score:  7.0
+
+Exploitability:         Proof-of-Concept
+Remediation Level:      Official Fix
+Report Confidence:      Confirmed
+
+CVE-2014-9421: kadmind doubly frees partial deserialization results
+
+CVSSv2 Vector: AV:N/AC:L/Au:S/C:C/I:C/A:C/E:POC/RL:OF/RC:C
+CVSSv2 Base Score:      9.0
+CVSSv2 Temporal Score:  7.0
+
+CVE-2014-9422: kadmind incorrectly validates server principal name
+
+CVSSv2 Vector: AV:N/AC:H/Au:S/C:P/I:P/A:C/E:POC/RL:OF/RC:C
+CVSSv2 Base Score:      6.1
+CVSSv2 Temporal Score:  4.8
+
+CVE-2014-9423: libgssrpc server applications leak uninitialized bytes
+
+CVSSv2 Vector: AV:N/AC:L/Au:N/C:P/I:N/A:N/E:H/RL:OF/RC:C
+CVSSv2 Base Score:      5.0
+CVSSv2 Temporal Score:  4.4
+
+Patch-Category: upstream
+---
+ src/kadmin/server/kadm_rpc_svc.c            | 12 +++---------
+ src/lib/gssapi/krb5/context_time.c          |  2 +-
+ src/lib/gssapi/krb5/export_sec_context.c    |  5 +++++
+ src/lib/gssapi/krb5/gssapiP_krb5.h          |  1 +
+ src/lib/gssapi/krb5/gssapi_krb5.c           |  2 +-
+ src/lib/gssapi/krb5/inq_context.c           |  2 +-
+ src/lib/gssapi/krb5/k5seal.c                |  2 +-
+ src/lib/gssapi/krb5/k5sealiov.c             |  2 +-
+ src/lib/gssapi/krb5/k5unseal.c              |  2 +-
+ src/lib/gssapi/krb5/k5unsealiov.c           |  2 +-
+ src/lib/gssapi/krb5/lucid_context.c         |  5 +++++
+ src/lib/gssapi/krb5/prf.c                   |  4 ++++
+ src/lib/gssapi/krb5/process_context_token.c | 17 ++++++++++++-----
+ src/lib/gssapi/krb5/wrap_size_limit.c       |  2 +-
+ src/lib/gssapi/mechglue/mglueP.h            |  1 -
+ src/lib/kadm5/kadm_rpc_xdr.c                |  2 ++
+ src/lib/rpc/auth_gssapi_misc.c              |  1 -
+ src/lib/rpc/svc_auth_gss.c                  | 25 ++-----------------------
+ 18 files changed, 42 insertions(+), 47 deletions(-)
+
+diff --git a/src/kadmin/server/kadm_rpc_svc.c b/src/kadmin/server/kadm_rpc_svc.c
+index 3837931..f4d2a7c 100644
+--- a/src/kadmin/server/kadm_rpc_svc.c
++++ b/src/kadmin/server/kadm_rpc_svc.c
+@@ -4,7 +4,7 @@
+  *
+  */
+ 
+-#include <k5-platform.h>
++#include <k5-int.h>
+ #include <gssrpc/rpc.h>
+ #include <gssapi/gssapi_krb5.h> /* for gss_nt_krb5_name */
+ #include <syslog.h>
+@@ -296,14 +296,8 @@ check_rpcsec_auth(struct svc_req *rqstp)
+      c1 = krb5_princ_component(kctx, princ, 0);
+      c2 = krb5_princ_component(kctx, princ, 1);
+      realm = krb5_princ_realm(kctx, princ);
+-     if (strncmp(handle->params.realm, realm->data, realm->length) == 0
+-	 && strncmp("kadmin", c1->data, c1->length) == 0) {
+-
+-	  if (strncmp("history", c2->data, c2->length) == 0)
+-	       goto fail_princ;
+-	  else
+-	       success = 1;
+-     }
++     success = data_eq_string(*realm, handle->params.realm) &&
++	     data_eq_string(*c1, "kadmin") && !data_eq_string(*c2, "history");
+ 
+ fail_princ:
+      if (!success) {
+diff --git a/src/lib/gssapi/krb5/context_time.c b/src/lib/gssapi/krb5/context_time.c
+index b3d1db0..a18cfb0 100644
+--- a/src/lib/gssapi/krb5/context_time.c
++++ b/src/lib/gssapi/krb5/context_time.c
+@@ -40,7 +40,7 @@ krb5_gss_context_time(minor_status, context_handle, time_rec)
+ 
+     ctx = (krb5_gss_ctx_id_rec *) context_handle;
+ 
+-    if (! ctx->established) {
++    if (ctx->terminated || !ctx->established) {
+         *minor_status = KG_CTX_INCOMPLETE;
+         return(GSS_S_NO_CONTEXT);
+     }
+diff --git a/src/lib/gssapi/krb5/export_sec_context.c b/src/lib/gssapi/krb5/export_sec_context.c
+index 18a3a34..1b3de68 100644
+--- a/src/lib/gssapi/krb5/export_sec_context.c
++++ b/src/lib/gssapi/krb5/export_sec_context.c
+@@ -45,6 +45,11 @@ krb5_gss_export_sec_context(minor_status, context_handle, interprocess_token)
+     *minor_status = 0;
+ 
+     ctx = (krb5_gss_ctx_id_t) *context_handle;
++    if (ctx->terminated) {
++        *minor_status = KG_CTX_INCOMPLETE;
++        return (GSS_S_NO_CONTEXT);
++    }
++
+     context = ctx->k5_context;
+     kret = krb5_gss_ser_init(context);
+     if (kret)
+diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
+index 0167816..42d16ad 100644
+--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
++++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
+@@ -204,6 +204,7 @@ typedef struct _krb5_gss_ctx_id_rec {
+     unsigned int established : 1;
+     unsigned int have_acceptor_subkey : 1;
+     unsigned int seed_init : 1;  /* XXX tested but never actually set */
++    unsigned int terminated : 1;
+     OM_uint32 gss_flags;
+     unsigned char seed[16];
+     krb5_gss_name_t here;
+diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c
+index a408259..088219a 100644
+--- a/src/lib/gssapi/krb5/gssapi_krb5.c
++++ b/src/lib/gssapi/krb5/gssapi_krb5.c
+@@ -369,7 +369,7 @@ krb5_gss_inquire_sec_context_by_oid (OM_uint32 *minor_status,
+ 
+     ctx = (krb5_gss_ctx_id_rec *) context_handle;
+ 
+-    if (!ctx->established)
++    if (ctx->terminated || !ctx->established)
+         return GSS_S_NO_CONTEXT;
+ 
+     for (i = 0; i < sizeof(krb5_gss_inquire_sec_context_by_oid_ops)/
+diff --git a/src/lib/gssapi/krb5/inq_context.c b/src/lib/gssapi/krb5/inq_context.c
+index eacb0fd..096df2a 100644
+--- a/src/lib/gssapi/krb5/inq_context.c
++++ b/src/lib/gssapi/krb5/inq_context.c
+@@ -105,7 +105,7 @@ krb5_gss_inquire_context(minor_status, context_handle, initiator_name,
+ 
+     ctx = (krb5_gss_ctx_id_rec *) context_handle;
+ 
+-    if (! ctx->established) {
++    if (ctx->terminated || !ctx->established) {
+         *minor_status = KG_CTX_INCOMPLETE;
+         return(GSS_S_NO_CONTEXT);
+     }
+diff --git a/src/lib/gssapi/krb5/k5seal.c b/src/lib/gssapi/krb5/k5seal.c
+index bd1e2a6..b11b615 100644
+--- a/src/lib/gssapi/krb5/k5seal.c
++++ b/src/lib/gssapi/krb5/k5seal.c
+@@ -342,7 +342,7 @@ kg_seal(minor_status, context_handle, conf_req_flag, qop_req,
+ 
+     ctx = (krb5_gss_ctx_id_rec *) context_handle;
+ 
+-    if (! ctx->established) {
++    if (ctx->terminated || !ctx->established) {
+         *minor_status = KG_CTX_INCOMPLETE;
+         return(GSS_S_NO_CONTEXT);
+     }
+diff --git a/src/lib/gssapi/krb5/k5sealiov.c b/src/lib/gssapi/krb5/k5sealiov.c
+index 0b99a77..0f80095 100644
+--- a/src/lib/gssapi/krb5/k5sealiov.c
++++ b/src/lib/gssapi/krb5/k5sealiov.c
+@@ -284,7 +284,7 @@ kg_seal_iov(OM_uint32 *minor_status,
+     }
+ 
+     ctx = (krb5_gss_ctx_id_rec *)context_handle;
+-    if (!ctx->established) {
++    if (ctx->terminated || !ctx->established) {
+         *minor_status = KG_CTX_INCOMPLETE;
+         return GSS_S_NO_CONTEXT;
+     }
+diff --git a/src/lib/gssapi/krb5/k5unseal.c b/src/lib/gssapi/krb5/k5unseal.c
+index b65c83c..9e78550 100644
+--- a/src/lib/gssapi/krb5/k5unseal.c
++++ b/src/lib/gssapi/krb5/k5unseal.c
+@@ -492,7 +492,7 @@ kg_unseal(minor_status, context_handle, input_token_buffer,
+ 
+     ctx = (krb5_gss_ctx_id_rec *) context_handle;
+ 
+-    if (! ctx->established) {
++    if (ctx->terminated || !ctx->established) {
+         *minor_status = KG_CTX_INCOMPLETE;
+         return(GSS_S_NO_CONTEXT);
+     }
+diff --git a/src/lib/gssapi/krb5/k5unsealiov.c b/src/lib/gssapi/krb5/k5unsealiov.c
+index 8d6a2da..191de2c 100644
+--- a/src/lib/gssapi/krb5/k5unsealiov.c
++++ b/src/lib/gssapi/krb5/k5unsealiov.c
+@@ -628,7 +628,7 @@ kg_unseal_iov(OM_uint32 *minor_status,
+     OM_uint32 code;
+ 
+     ctx = (krb5_gss_ctx_id_rec *)context_handle;
+-    if (!ctx->established) {
++    if (ctx->terminated || !ctx->established) {
+         *minor_status = KG_CTX_INCOMPLETE;
+         return GSS_S_NO_CONTEXT;
+     }
+diff --git a/src/lib/gssapi/krb5/lucid_context.c b/src/lib/gssapi/krb5/lucid_context.c
+index dc129e1..50d8cc9 100644
+--- a/src/lib/gssapi/krb5/lucid_context.c
++++ b/src/lib/gssapi/krb5/lucid_context.c
+@@ -75,6 +75,11 @@ gss_krb5int_export_lucid_sec_context(
+     *minor_status = 0;
+     *data_set = GSS_C_NO_BUFFER_SET;
+ 
++    if (ctx->terminated || !ctx->established) {
++        *minor_status = KG_CTX_INCOMPLETE;
++        return GSS_S_NO_CONTEXT;
++    }
++
+     retval = generic_gss_oid_decompose(minor_status,
+                                        GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID,
+                                        GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH,
+diff --git a/src/lib/gssapi/krb5/prf.c b/src/lib/gssapi/krb5/prf.c
+index a0fbcda..4831f9f 100644
+--- a/src/lib/gssapi/krb5/prf.c
++++ b/src/lib/gssapi/krb5/prf.c
+@@ -60,6 +60,10 @@ krb5_gss_pseudo_random(OM_uint32 *minor_status,
+     ns.data = NULL;
+ 
+     ctx = (krb5_gss_ctx_id_t)context;
++    if (ctx->terminated || !ctx->established) {
++        *minor_status = KG_CTX_INCOMPLETE;
++        return GSS_S_NO_CONTEXT;
++    }
+ 
+     switch (prf_key) {
+     case GSS_C_PRF_KEY_FULL:
+diff --git a/src/lib/gssapi/krb5/process_context_token.c b/src/lib/gssapi/krb5/process_context_token.c
+index ae33180..a672f48 100644
+--- a/src/lib/gssapi/krb5/process_context_token.c
++++ b/src/lib/gssapi/krb5/process_context_token.c
+@@ -39,11 +39,18 @@ krb5_gss_process_context_token(minor_status, context_handle,
+ 
+     ctx = (krb5_gss_ctx_id_t) context_handle;
+ 
+-    if (! ctx->established) {
++    if (ctx->terminated || !ctx->established) {
+         *minor_status = KG_CTX_INCOMPLETE;
+         return(GSS_S_NO_CONTEXT);
+     }
+ 
++    /* We only support context deletion tokens for now, and RFC 4121 does not
++     * define a context deletion token. */
++    if (ctx->proto) {
++        *minor_status = 0;
++        return(GSS_S_DEFECTIVE_TOKEN);
++    }
++
+     /* "unseal" the token */
+ 
+     if (GSS_ERROR(majerr = kg_unseal(minor_status, context_handle,
+@@ -52,8 +59,8 @@ krb5_gss_process_context_token(minor_status, context_handle,
+                                      KG_TOK_DEL_CTX)))
+         return(majerr);
+ 
+-    /* that's it.  delete the context */
+-
+-    return(krb5_gss_delete_sec_context(minor_status, &context_handle,
+-                                       GSS_C_NO_BUFFER));
++    /* Mark the context as terminated, but do not delete it (as that would
++     * leave the caller with a dangling context handle). */
++    ctx->terminated = 1;
++    return(GSS_S_COMPLETE);
+ }
+diff --git a/src/lib/gssapi/krb5/wrap_size_limit.c b/src/lib/gssapi/krb5/wrap_size_limit.c
+index 7bc4221..ed5c599 100644
+--- a/src/lib/gssapi/krb5/wrap_size_limit.c
++++ b/src/lib/gssapi/krb5/wrap_size_limit.c
+@@ -95,7 +95,7 @@ krb5_gss_wrap_size_limit(minor_status, context_handle, conf_req_flag,
+     }
+ 
+     ctx = (krb5_gss_ctx_id_rec *) context_handle;
+-    if (! ctx->established) {
++    if (ctx->terminated || !ctx->established) {
+         *minor_status = KG_CTX_INCOMPLETE;
+         return(GSS_S_NO_CONTEXT);
+     }
+diff --git a/src/lib/gssapi/mechglue/mglueP.h b/src/lib/gssapi/mechglue/mglueP.h
+index e56b9c1..2b5145e 100644
+--- a/src/lib/gssapi/mechglue/mglueP.h
++++ b/src/lib/gssapi/mechglue/mglueP.h
+@@ -25,7 +25,6 @@ do {								\
+  */
+ typedef struct gss_union_ctx_id_struct {
+ 	struct gss_union_ctx_id_struct *loopback;
+-	struct gss_union_ctx_id_struct *interposer;
+ 	gss_OID			mech_type;
+ 	gss_ctx_id_t		internal_ctx_id;
+ } gss_union_ctx_id_desc, *gss_union_ctx_id_t;
+diff --git a/src/lib/kadm5/kadm_rpc_xdr.c b/src/lib/kadm5/kadm_rpc_xdr.c
+index 42ac783..975f94c 100644
+--- a/src/lib/kadm5/kadm_rpc_xdr.c
++++ b/src/lib/kadm5/kadm_rpc_xdr.c
+@@ -320,6 +320,7 @@ bool_t xdr_krb5_tl_data(XDR *xdrs, krb5_tl_data **tl_data_head)
+ 	       free(tl);
+ 	       tl = tl2;
+ 	  }
++	  *tl_data_head = NULL;
+ 	  break;
+ 
+      case XDR_ENCODE:
+@@ -1096,6 +1097,7 @@ xdr_krb5_principal(XDR *xdrs, krb5_principal *objp)
+     case XDR_FREE:
+ 	if(*objp != NULL)
+ 	    krb5_free_principal(context, *objp);
++	*objp = NULL;
+ 	break;
+     }
+     return TRUE;
+diff --git a/src/lib/rpc/auth_gssapi_misc.c b/src/lib/rpc/auth_gssapi_misc.c
+index 53bdb98..a05ea19 100644
+--- a/src/lib/rpc/auth_gssapi_misc.c
++++ b/src/lib/rpc/auth_gssapi_misc.c
+@@ -322,7 +322,6 @@ bool_t auth_gssapi_unwrap_data(
+      if (! (*xdr_func)(&temp_xdrs, xdr_ptr)) {
+ 	  PRINTF(("gssapi_unwrap_data: deserializing arguments failed\n"));
+ 	  gss_release_buffer(minor, &out_buf);
+-	  xdr_free(xdr_func, xdr_ptr);
+ 	  XDR_DESTROY(&temp_xdrs);
+ 	  return FALSE;
+      }
+diff --git a/src/lib/rpc/svc_auth_gss.c b/src/lib/rpc/svc_auth_gss.c
+index 8da7003..ea8149b 100644
+--- a/src/lib/rpc/svc_auth_gss.c
++++ b/src/lib/rpc/svc_auth_gss.c
+@@ -68,16 +68,6 @@ extern const gss_OID_desc * const gss_mech_spkm3;
+ 
+ extern SVCAUTH svc_auth_none;
+ 
+-/*
+- * from mit-krb5-1.2.1 mechglue/mglueP.h:
+- * Array of context IDs typed by mechanism OID
+- */
+-typedef struct gss_union_ctx_id_t {
+-  gss_OID     mech_type;
+-  gss_ctx_id_t    internal_ctx_id;
+-} gss_union_ctx_id_desc, *gss_union_ctx_id_t;
+-
+-
+ static auth_gssapi_log_badauth_func log_badauth = NULL;
+ static caddr_t log_badauth_data = NULL;
+ static auth_gssapi_log_badauth2_func log_badauth2 = NULL;
+@@ -242,16 +232,8 @@ svcauth_gss_accept_sec_context(struct svc_req *rqst,
+ 		gd->ctx = GSS_C_NO_CONTEXT;
+ 		goto errout;
+ 	}
+-	/*
+-	 * ANDROS: krb5 mechglue returns ctx of size 8 - two pointers,
+-	 * one to the mechanism oid, one to the internal_ctx_id
+-	 */
+-	if ((gr->gr_ctx.value = mem_alloc(sizeof(gss_union_ctx_id_desc))) == NULL) {
+-		fprintf(stderr, "svcauth_gss_accept_context: out of memory\n");
+-		goto errout;
+-	}
+-	memcpy(gr->gr_ctx.value, gd->ctx, sizeof(gss_union_ctx_id_desc));
+-	gr->gr_ctx.length = sizeof(gss_union_ctx_id_desc);
++	gr->gr_ctx.value = "xxxx";
++	gr->gr_ctx.length = 4;
+ 
+ 	/* gr->gr_win = 0x00000005; ANDROS: for debugging linux kernel version...  */
+ 	gr->gr_win = sizeof(gd->seqmask) * 8;
+@@ -523,8 +505,6 @@ gssrpc__svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg,
+ 
+ 		if (!svcauth_gss_nextverf(rqst, htonl(gr.gr_win))) {
+ 			gss_release_buffer(&min_stat, &gr.gr_token);
+-			mem_free(gr.gr_ctx.value,
+-				 sizeof(gss_union_ctx_id_desc));
+ 			ret_freegc (AUTH_FAILED);
+ 		}
+ 		*no_dispatch = TRUE;
+@@ -534,7 +514,6 @@ gssrpc__svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg,
+ 
+ 		gss_release_buffer(&min_stat, &gr.gr_token);
+ 		gss_release_buffer(&min_stat, &gd->checksum);
+-		mem_free(gr.gr_ctx.value, sizeof(gss_union_ctx_id_desc));
+ 		if (!call_stat)
+ 			ret_freegc (AUTH_FAILED);
+ 
diff --git a/src/kadmin/server/kadm_rpc_svc.c b/src/kadmin/server/kadm_rpc_svc.c
index 3837931..f4d2a7c 100644
--- a/src/kadmin/server/kadm_rpc_svc.c
+++ b/src/kadmin/server/kadm_rpc_svc.c
@@ -4,7 +4,7 @@
  *
  */
 
-#include <k5-platform.h>
+#include <k5-int.h>
 #include <gssrpc/rpc.h>
 #include <gssapi/gssapi_krb5.h> /* for gss_nt_krb5_name */
 #include <syslog.h>
@@ -296,14 +296,8 @@ check_rpcsec_auth(struct svc_req *rqstp)
      c1 = krb5_princ_component(kctx, princ, 0);
      c2 = krb5_princ_component(kctx, princ, 1);
      realm = krb5_princ_realm(kctx, princ);
-     if (strncmp(handle->params.realm, realm->data, realm->length) == 0
-	 && strncmp("kadmin", c1->data, c1->length) == 0) {
-
-	  if (strncmp("history", c2->data, c2->length) == 0)
-	       goto fail_princ;
-	  else
-	       success = 1;
-     }
+     success = data_eq_string(*realm, handle->params.realm) &&
+	     data_eq_string(*c1, "kadmin") && !data_eq_string(*c2, "history");
 
 fail_princ:
      if (!success) {
diff --git a/src/lib/gssapi/krb5/context_time.c b/src/lib/gssapi/krb5/context_time.c
index b3d1db0..a18cfb0 100644
--- a/src/lib/gssapi/krb5/context_time.c
+++ b/src/lib/gssapi/krb5/context_time.c
@@ -40,7 +40,7 @@ krb5_gss_context_time(minor_status, context_handle, time_rec)
 
     ctx = (krb5_gss_ctx_id_rec *) context_handle;
 
-    if (! ctx->established) {
+    if (ctx->terminated || !ctx->established) {
         *minor_status = KG_CTX_INCOMPLETE;
         return(GSS_S_NO_CONTEXT);
     }
diff --git a/src/lib/gssapi/krb5/export_sec_context.c b/src/lib/gssapi/krb5/export_sec_context.c
index 18a3a34..1b3de68 100644
--- a/src/lib/gssapi/krb5/export_sec_context.c
+++ b/src/lib/gssapi/krb5/export_sec_context.c
@@ -45,6 +45,11 @@ krb5_gss_export_sec_context(minor_status, context_handle, interprocess_token)
     *minor_status = 0;
 
     ctx = (krb5_gss_ctx_id_t) *context_handle;
+    if (ctx->terminated) {
+        *minor_status = KG_CTX_INCOMPLETE;
+        return (GSS_S_NO_CONTEXT);
+    }
+
     context = ctx->k5_context;
     kret = krb5_gss_ser_init(context);
     if (kret)
diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
index 0167816..42d16ad 100644
--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
+++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
@@ -204,6 +204,7 @@ typedef struct _krb5_gss_ctx_id_rec {
     unsigned int established : 1;
     unsigned int have_acceptor_subkey : 1;
     unsigned int seed_init : 1;  /* XXX tested but never actually set */
+    unsigned int terminated : 1;
     OM_uint32 gss_flags;
     unsigned char seed[16];
     krb5_gss_name_t here;
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c
index a408259..088219a 100644
--- a/src/lib/gssapi/krb5/gssapi_krb5.c
+++ b/src/lib/gssapi/krb5/gssapi_krb5.c
@@ -369,7 +369,7 @@ krb5_gss_inquire_sec_context_by_oid (OM_uint32 *minor_status,
 
     ctx = (krb5_gss_ctx_id_rec *) context_handle;
 
-    if (!ctx->established)
+    if (ctx->terminated || !ctx->established)
         return GSS_S_NO_CONTEXT;
 
     for (i = 0; i < sizeof(krb5_gss_inquire_sec_context_by_oid_ops)/
diff --git a/src/lib/gssapi/krb5/inq_context.c b/src/lib/gssapi/krb5/inq_context.c
index eacb0fd..096df2a 100644
--- a/src/lib/gssapi/krb5/inq_context.c
+++ b/src/lib/gssapi/krb5/inq_context.c
@@ -105,7 +105,7 @@ krb5_gss_inquire_context(minor_status, context_handle, initiator_name,
 
     ctx = (krb5_gss_ctx_id_rec *) context_handle;
 
-    if (! ctx->established) {
+    if (ctx->terminated || !ctx->established) {
         *minor_status = KG_CTX_INCOMPLETE;
         return(GSS_S_NO_CONTEXT);
     }
diff --git a/src/lib/gssapi/krb5/k5seal.c b/src/lib/gssapi/krb5/k5seal.c
index bd1e2a6..b11b615 100644
--- a/src/lib/gssapi/krb5/k5seal.c
+++ b/src/lib/gssapi/krb5/k5seal.c
@@ -342,7 +342,7 @@ kg_seal(minor_status, context_handle, conf_req_flag, qop_req,
 
     ctx = (krb5_gss_ctx_id_rec *) context_handle;
 
-    if (! ctx->established) {
+    if (ctx->terminated || !ctx->established) {
         *minor_status = KG_CTX_INCOMPLETE;
         return(GSS_S_NO_CONTEXT);
     }
diff --git a/src/lib/gssapi/krb5/k5sealiov.c b/src/lib/gssapi/krb5/k5sealiov.c
index 0b99a77..0f80095 100644
--- a/src/lib/gssapi/krb5/k5sealiov.c
+++ b/src/lib/gssapi/krb5/k5sealiov.c
@@ -284,7 +284,7 @@ kg_seal_iov(OM_uint32 *minor_status,
     }
 
     ctx = (krb5_gss_ctx_id_rec *)context_handle;
-    if (!ctx->established) {
+    if (ctx->terminated || !ctx->established) {
         *minor_status = KG_CTX_INCOMPLETE;
         return GSS_S_NO_CONTEXT;
     }
diff --git a/src/lib/gssapi/krb5/k5unseal.c b/src/lib/gssapi/krb5/k5unseal.c
index b65c83c..9e78550 100644
--- a/src/lib/gssapi/krb5/k5unseal.c
+++ b/src/lib/gssapi/krb5/k5unseal.c
@@ -492,7 +492,7 @@ kg_unseal(minor_status, context_handle, input_token_buffer,
 
     ctx = (krb5_gss_ctx_id_rec *) context_handle;
 
-    if (! ctx->established) {
+    if (ctx->terminated || !ctx->established) {
         *minor_status = KG_CTX_INCOMPLETE;
         return(GSS_S_NO_CONTEXT);
     }
diff --git a/src/lib/gssapi/krb5/k5unsealiov.c b/src/lib/gssapi/krb5/k5unsealiov.c
index 8d6a2da..191de2c 100644
--- a/src/lib/gssapi/krb5/k5unsealiov.c
+++ b/src/lib/gssapi/krb5/k5unsealiov.c
@@ -628,7 +628,7 @@ kg_unseal_iov(OM_uint32 *minor_status,
     OM_uint32 code;
 
     ctx = (krb5_gss_ctx_id_rec *)context_handle;
-    if (!ctx->established) {
+    if (ctx->terminated || !ctx->established) {
         *minor_status = KG_CTX_INCOMPLETE;
         return GSS_S_NO_CONTEXT;
     }
diff --git a/src/lib/gssapi/krb5/lucid_context.c b/src/lib/gssapi/krb5/lucid_context.c
index dc129e1..50d8cc9 100644
--- a/src/lib/gssapi/krb5/lucid_context.c
+++ b/src/lib/gssapi/krb5/lucid_context.c
@@ -75,6 +75,11 @@ gss_krb5int_export_lucid_sec_context(
     *minor_status = 0;
     *data_set = GSS_C_NO_BUFFER_SET;
 
+    if (ctx->terminated || !ctx->established) {
+        *minor_status = KG_CTX_INCOMPLETE;
+        return GSS_S_NO_CONTEXT;
+    }
+
     retval = generic_gss_oid_decompose(minor_status,
                                        GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID,
                                        GSS_KRB5_EXPORT_LUCID_SEC_CONTEXT_OID_LENGTH,
diff --git a/src/lib/gssapi/krb5/prf.c b/src/lib/gssapi/krb5/prf.c
index a0fbcda..4831f9f 100644
--- a/src/lib/gssapi/krb5/prf.c
+++ b/src/lib/gssapi/krb5/prf.c
@@ -60,6 +60,10 @@ krb5_gss_pseudo_random(OM_uint32 *minor_status,
     ns.data = NULL;
 
     ctx = (krb5_gss_ctx_id_t)context;
+    if (ctx->terminated || !ctx->established) {
+        *minor_status = KG_CTX_INCOMPLETE;
+        return GSS_S_NO_CONTEXT;
+    }
 
     switch (prf_key) {
     case GSS_C_PRF_KEY_FULL:
diff --git a/src/lib/gssapi/krb5/process_context_token.c b/src/lib/gssapi/krb5/process_context_token.c
index ae33180..a672f48 100644
--- a/src/lib/gssapi/krb5/process_context_token.c
+++ b/src/lib/gssapi/krb5/process_context_token.c
@@ -39,11 +39,18 @@ krb5_gss_process_context_token(minor_status, context_handle,
 
     ctx = (krb5_gss_ctx_id_t) context_handle;
 
-    if (! ctx->established) {
+    if (ctx->terminated || !ctx->established) {
         *minor_status = KG_CTX_INCOMPLETE;
         return(GSS_S_NO_CONTEXT);
     }
 
+    /* We only support context deletion tokens for now, and RFC 4121 does not
+     * define a context deletion token. */
+    if (ctx->proto) {
+        *minor_status = 0;
+        return(GSS_S_DEFECTIVE_TOKEN);
+    }
+
     /* "unseal" the token */
 
     if (GSS_ERROR(majerr = kg_unseal(minor_status, context_handle,
@@ -52,8 +59,8 @@ krb5_gss_process_context_token(minor_status, context_handle,
                                      KG_TOK_DEL_CTX)))
         return(majerr);
 
-    /* that's it.  delete the context */
-
-    return(krb5_gss_delete_sec_context(minor_status, &context_handle,
-                                       GSS_C_NO_BUFFER));
+    /* Mark the context as terminated, but do not delete it (as that would
+     * leave the caller with a dangling context handle). */
+    ctx->terminated = 1;
+    return(GSS_S_COMPLETE);
 }
diff --git a/src/lib/gssapi/krb5/wrap_size_limit.c b/src/lib/gssapi/krb5/wrap_size_limit.c
index 7bc4221..ed5c599 100644
--- a/src/lib/gssapi/krb5/wrap_size_limit.c
+++ b/src/lib/gssapi/krb5/wrap_size_limit.c
@@ -95,7 +95,7 @@ krb5_gss_wrap_size_limit(minor_status, context_handle, conf_req_flag,
     }
 
     ctx = (krb5_gss_ctx_id_rec *) context_handle;
-    if (! ctx->established) {
+    if (ctx->terminated || !ctx->established) {
         *minor_status = KG_CTX_INCOMPLETE;
         return(GSS_S_NO_CONTEXT);
     }
diff --git a/src/lib/gssapi/mechglue/mglueP.h b/src/lib/gssapi/mechglue/mglueP.h
index e56b9c1..2b5145e 100644
--- a/src/lib/gssapi/mechglue/mglueP.h
+++ b/src/lib/gssapi/mechglue/mglueP.h
@@ -25,7 +25,6 @@ do {								\
  */
 typedef struct gss_union_ctx_id_struct {
 	struct gss_union_ctx_id_struct *loopback;
-	struct gss_union_ctx_id_struct *interposer;
 	gss_OID			mech_type;
 	gss_ctx_id_t		internal_ctx_id;
 } gss_union_ctx_id_desc, *gss_union_ctx_id_t;
diff --git a/src/lib/kadm5/kadm_rpc_xdr.c b/src/lib/kadm5/kadm_rpc_xdr.c
index 42ac783..975f94c 100644
--- a/src/lib/kadm5/kadm_rpc_xdr.c
+++ b/src/lib/kadm5/kadm_rpc_xdr.c
@@ -320,6 +320,7 @@ bool_t xdr_krb5_tl_data(XDR *xdrs, krb5_tl_data **tl_data_head)
 	       free(tl);
 	       tl = tl2;
 	  }
+	  *tl_data_head = NULL;
 	  break;
 
      case XDR_ENCODE:
@@ -1096,6 +1097,7 @@ xdr_krb5_principal(XDR *xdrs, krb5_principal *objp)
     case XDR_FREE:
 	if(*objp != NULL)
 	    krb5_free_principal(context, *objp);
+	*objp = NULL;
 	break;
     }
     return TRUE;
diff --git a/src/lib/rpc/auth_gssapi_misc.c b/src/lib/rpc/auth_gssapi_misc.c
index 53bdb98..a05ea19 100644
--- a/src/lib/rpc/auth_gssapi_misc.c
+++ b/src/lib/rpc/auth_gssapi_misc.c
@@ -322,7 +322,6 @@ bool_t auth_gssapi_unwrap_data(
      if (! (*xdr_func)(&temp_xdrs, xdr_ptr)) {
 	  PRINTF(("gssapi_unwrap_data: deserializing arguments failed\n"));
 	  gss_release_buffer(minor, &out_buf);
-	  xdr_free(xdr_func, xdr_ptr);
 	  XDR_DESTROY(&temp_xdrs);
 	  return FALSE;
      }
diff --git a/src/lib/rpc/svc_auth_gss.c b/src/lib/rpc/svc_auth_gss.c
index 8da7003..ea8149b 100644
--- a/src/lib/rpc/svc_auth_gss.c
+++ b/src/lib/rpc/svc_auth_gss.c
@@ -68,16 +68,6 @@ extern const gss_OID_desc * const gss_mech_spkm3;
 
 extern SVCAUTH svc_auth_none;
 
-/*
- * from mit-krb5-1.2.1 mechglue/mglueP.h:
- * Array of context IDs typed by mechanism OID
- */
-typedef struct gss_union_ctx_id_t {
-  gss_OID     mech_type;
-  gss_ctx_id_t    internal_ctx_id;
-} gss_union_ctx_id_desc, *gss_union_ctx_id_t;
-
-
 static auth_gssapi_log_badauth_func log_badauth = NULL;
 static caddr_t log_badauth_data = NULL;
 static auth_gssapi_log_badauth2_func log_badauth2 = NULL;
@@ -242,16 +232,8 @@ svcauth_gss_accept_sec_context(struct svc_req *rqst,
 		gd->ctx = GSS_C_NO_CONTEXT;
 		goto errout;
 	}
-	/*
-	 * ANDROS: krb5 mechglue returns ctx of size 8 - two pointers,
-	 * one to the mechanism oid, one to the internal_ctx_id
-	 */
-	if ((gr->gr_ctx.value = mem_alloc(sizeof(gss_union_ctx_id_desc))) == NULL) {
-		fprintf(stderr, "svcauth_gss_accept_context: out of memory\n");
-		goto errout;
-	}
-	memcpy(gr->gr_ctx.value, gd->ctx, sizeof(gss_union_ctx_id_desc));
-	gr->gr_ctx.length = sizeof(gss_union_ctx_id_desc);
+	gr->gr_ctx.value = "xxxx";
+	gr->gr_ctx.length = 4;
 
 	/* gr->gr_win = 0x00000005; ANDROS: for debugging linux kernel version...  */
 	gr->gr_win = sizeof(gd->seqmask) * 8;
@@ -523,8 +505,6 @@ gssrpc__svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg,
 
 		if (!svcauth_gss_nextverf(rqst, htonl(gr.gr_win))) {
 			gss_release_buffer(&min_stat, &gr.gr_token);
-			mem_free(gr.gr_ctx.value,
-				 sizeof(gss_union_ctx_id_desc));
 			ret_freegc (AUTH_FAILED);
 		}
 		*no_dispatch = TRUE;
@@ -534,7 +514,6 @@ gssrpc__svcauth_gss(struct svc_req *rqst, struct rpc_msg *msg,
 
 		gss_release_buffer(&min_stat, &gr.gr_token);
 		gss_release_buffer(&min_stat, &gd->checksum);
-		mem_free(gr.gr_ctx.value, sizeof(gss_union_ctx_id_desc));
 		if (!call_stat)
 			ret_freegc (AUTH_FAILED);
 



unblock krb5/1.12.1+dfsg-17

-- System Information:
Debian Release: jessie/sid
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable'), (250, 'testing'), (200, 'unstable')
Architecture: amd64 (x86_64)

Kernel: Linux 3.16-2-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.utf8, LC_CTYPE=en_US.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash


Reply to: