components/krb5/patches/053-kernel-mech.patch
author Neng Xue <neng.xue@oracle.com>
Fri, 14 Oct 2016 11:36:01 -0700
changeset 7111 a0e4f5518caa
parent 6978 14cbeb78966a
permissions -rw-r--r--
23500659 Setting ADIHEAP finds issues in GSS-API

#
# This patch updates the MIT Kerberos mechanism to integrate with the kernel
# mechanism in Solaris with the following updates:
#
# 1. The MIT implementation uses a combination of static and dynamically
# linked mechanisms, whereas Solaris only used dynamically loaded mechanisms.
# The statically loaded mech for krb does not include a kernel module by
# default for MIT and any dynamically loadable mech is not added when the mech
# has the same OID. Therefore this patch adds the kernel module with the static
# linking method during mech initialization.
#
# 2.  After implementing 1. another problem occurs when actually messaging
# with the kernel.  Specifically the security context import fails due to
# differences in messaging information as follows:
#
#    a. KV5M_CONTEXT
#    b. KV5M_AUTH_CONTEXT
#    c. KV5M_AUTHDATA
#    d. KV5M_AUTHDATA_CONTEXT
#    e. big_endian
#    f. kernel uses queue structure vs. sequence state
#
# Using the LUCID context would pare down the information to what the kernel
# needs, but currently the LUCID functions do not serialize this data compared
# to the normal export security context routine.
#
# Note: That this patch is specific to the Solaris kernel implementation and
# therefore should not be considered as an upstream contribution to MIT.
# Patch source: in-house
#
--- a/src/lib/gssapi/generic/Makefile.in
+++ b/src/lib/gssapi/generic/Makefile.in
@@ -66,6 +66,7 @@ SRCS = \
 	$(srcdir)/util_buffer.c \
 	$(srcdir)/util_buffer_set.c \
 	$(srcdir)/util_errmap.c \
+	$(srcdir)/util_ordering.c \
 	$(srcdir)/util_set.c \
 	$(srcdir)/util_seqstate.c \
 	$(srcdir)/util_token.c \
@@ -83,6 +84,7 @@ OBJS = \
 	$(OUTPRE)util_buffer.$(OBJEXT) \
 	$(OUTPRE)util_buffer_set.$(OBJEXT) \
 	$(OUTPRE)util_errmap.$(OBJEXT) \
+	$(OUTPRE)util_ordering.$(OBJEXT) \
 	$(OUTPRE)util_set.$(OBJEXT) \
 	$(OUTPRE)util_seqstate.$(OBJEXT) \
 	$(OUTPRE)util_token.$(OBJEXT) \
@@ -98,6 +100,7 @@ STLIBOBJS = \
 	util_buffer.o \
 	util_buffer_set.o \
 	util_errmap.o \
+	util_ordering.o \
 	util_set.o \
 	util_seqstate.o \
 	util_token.o \
--- a/src/lib/gssapi/generic/deps
+++ b/src/lib/gssapi/generic/deps
@@ -64,6 +64,13 @@ util_errmap.so util_errmap.po $(OUTPRE)u
   $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/krb5.h \
   errmap.h gssapiP_generic.h gssapi_err_generic.h gssapi_ext.h \
   gssapi_generic.h util_errmap.c
+util_ordering.so util_ordering.po $(OUTPRE)util_ordering.$(OBJEXT): \
+  $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
+  $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(COM_ERR_DEPS) \
+  $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-platform.h \
+  $(top_srcdir)/include/k5-thread.h gssapiP_generic.h \
+  gssapi_err_generic.h gssapi_ext.h gssapi_generic.h \
+  util_ordering.c
 util_set.so util_set.po $(OUTPRE)util_set.$(OBJEXT): \
   $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \
   $(BUILDTOP)/include/gssapi/gssapi_alloc.h $(COM_ERR_DEPS) \
--- a/src/lib/gssapi/generic/gssapiP_generic.h
+++ b/src/lib/gssapi/generic/gssapiP_generic.h
@@ -116,6 +116,12 @@
 #define g_seqstate_size         gssint_g_seqstate_size
 #define g_seqstate_externalize  gssint_g_seqstate_externalize
 #define g_seqstate_internalize  gssint_g_seqstate_internalize
+#define	g_order_init		gssint_g_order_init
+#define	g_order_check		gssint_g_order_check
+#define	g_order_free		gssint_g_order_free
+#define	g_queue_size		gssint_g_queue_size
+#define	g_queue_externalize	gssint_g_queue_externalize
+#define	g_queue_internalize	gssint_g_queue_internalize
 #define g_canonicalize_host     gssint_g_canonicalize_host
 #define g_local_host_name       gssint_g_local_host_name
 #define g_strdup                gssint_g_strdup
@@ -185,6 +191,19 @@ long g_seqstate_externalize(g_seqnum_sta
 long g_seqstate_internalize(g_seqnum_state *state_out, unsigned char **buf,
                             size_t *lenremain);
 
+gss_int32 g_order_init (void **queue, uint64_t seqnum,
+				  int do_replay, int do_sequence, int wide);
+
+gss_int32 g_order_check (void **queue, uint64_t seqnum);
+
+void g_order_free (void **queue);
+
+gss_uint32 g_queue_size(void *vqueue, size_t *sizep);
+gss_uint32 g_queue_externalize(void *vqueue, unsigned char **buf,
+			       size_t *lenremain);
+gss_uint32 g_queue_internalize(void **vqueue, unsigned char **buf,
+			       size_t *lenremain);
+
 char *g_strdup (char *str);
 
 /** declarations of internal name mechanism functions **/
--- a/src/lib/gssapi/krb5/accept_sec_context.c
+++ b/src/lib/gssapi/krb5/accept_sec_context.c
@@ -435,6 +435,7 @@ kg_accept_krb5(minor_status, context_han
     char *sptr;
     OM_uint32 tmp;
     size_t md5len;
+    int bigend;
     krb5_gss_cred_id_t cred = 0;
     krb5_data ap_rep, ap_req;
     unsigned int i;
@@ -701,6 +702,7 @@ kg_accept_krb5(minor_status, context_han
         gss_flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG;
         if (ap_req_options & AP_OPTS_MUTUAL_REQUIRED)
             gss_flags |= GSS_C_MUTUAL_FLAG;
+	bigend = 0;
     } else {
         /* gss krb5 v1 */
 
@@ -728,14 +730,22 @@ kg_accept_krb5(minor_status, context_han
         }
 
         ptr = (unsigned char *) authdat->checksum->contents;
+	bigend = 0;
 
-        TREAD_INT(ptr, tmp, 0);
+        TREAD_INT(ptr, tmp, bigend);
 
-        if (tmp != md5len) {
-            code = KG_BAD_LENGTH;
-            major_status = GSS_S_FAILURE;
-            goto fail;
-        }
+	if (tmp != md5len) {
+	    ptr = (unsigned char *) authdat->checksum->contents;
+	    bigend = 1;
+
+	    TREAD_INT(ptr, tmp, bigend);
+
+	    if (tmp != md5len) {
+		code = KG_BAD_LENGTH;
+		major_status = GSS_S_FAILURE;
+		goto fail;
+	    }
+	}
 
         /*
           The following section of code attempts to implement the
@@ -776,7 +786,7 @@ kg_accept_krb5(minor_status, context_han
 
         /* Read the token flags.  Remember if GSS_C_DELEG_FLAG was set, but
          * mask it out until we actually read a delegated credential. */
-        TREAD_INT(ptr, gss_flags, 0);
+        TREAD_INT(ptr, gss_flags, bigend);
         token_deleg_flag = (gss_flags & GSS_C_DELEG_FLAG);
         gss_flags &= ~GSS_C_DELEG_FLAG;
 
@@ -785,8 +795,8 @@ kg_accept_krb5(minor_status, context_han
         i = authdat->checksum->length - 24;
         if (i && token_deleg_flag) {
             if (i >= 4) {
-                TREAD_INT16(ptr, option_id, 0);
-                TREAD_INT16(ptr, option.length, 0);
+                TREAD_INT16(ptr, option_id, bigend);
+                TREAD_INT16(ptr, option.length, bigend);
                 i -= 4;
 
                 if (i < option.length) {
@@ -883,6 +893,7 @@ kg_accept_krb5(minor_status, context_han
                                       GSS_C_DCE_STYLE | GSS_C_IDENTIFY_FLAG |
                                       GSS_C_EXTENDED_ERROR_FLAG)));
     ctx->seed_init = 0;
+    ctx->big_endian = bigend;
     ctx->cred_rcache = cred_rcache;
 
     /* XXX move this into gss_name_t */
--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
+++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
@@ -205,6 +205,7 @@ typedef struct _krb5_gss_ctx_id_rec {
     krb5_magic magic;
     unsigned int initiate : 1;   /* nonzero if initiating, zero if accepting */
     unsigned int established : 1;
+    unsigned int big_endian : 1;
     unsigned int have_acceptor_subkey : 1;
     unsigned int seed_init : 1;  /* XXX tested but never actually set */
     unsigned int terminated : 1;
--- a/src/lib/gssapi/krb5/gssapi_krb5.c
+++ b/src/lib/gssapi/krb5/gssapi_krb5.c
@@ -1046,6 +1046,7 @@ static int gss_krb5mechglue_init(void)
 
     mech_krb5.mechNameStr = "kerberos_v5";
     mech_krb5.mech_type = (gss_OID)gss_mech_krb5;
+    mech_krb5.kmodName = "kmech_krb5";
     gssint_register_mechinfo(&mech_krb5);
 
     mech_krb5.mechNameStr = "kerberos_v5_old";
--- a/src/lib/gssapi/krb5/import_sec_context.c
+++ b/src/lib/gssapi/krb5/import_sec_context.c
@@ -107,7 +107,6 @@ krb5_gss_import_sec_context(minor_status
         krb5_free_context(context);
         return(GSS_S_FAILURE);
     }
-    krb5_free_context(context);
 
     ctx->mech_used = krb5_gss_convert_static_mech_oid(ctx->mech_used);
 
--- a/src/lib/gssapi/krb5/ser_sctx.c
+++ b/src/lib/gssapi/krb5/ser_sctx.c
@@ -150,6 +150,22 @@ kg_oid_size(kcontext, arg, sizep)
 }
 
 static krb5_error_code
+kg_queue_externalize(kcontext, arg, buffer, lenremain)
+    krb5_context        kcontext;
+    krb5_pointer        arg;
+    krb5_octet          **buffer;
+    size_t              *lenremain;
+{
+    krb5_error_code err;
+    err = krb5_ser_pack_int32(KV5M_GSS_QUEUE, buffer, lenremain);
+    if (err == 0)
+        err = g_queue_externalize(arg, buffer, lenremain);
+    if (err == 0)
+        err = krb5_ser_pack_int32(KV5M_GSS_QUEUE, buffer, lenremain);
+    return err;
+}
+
+static krb5_error_code
 kg_seqstate_externalize(kcontext, arg, buffer, lenremain)
     krb5_context        kcontext;
     g_seqnum_state      arg;
@@ -166,6 +182,48 @@ kg_seqstate_externalize(kcontext, arg, b
 }
 
 static krb5_error_code
+kg_queue_internalize(kcontext, argp, buffer, lenremain)
+    krb5_context        kcontext;
+    krb5_pointer        *argp;
+    krb5_octet          **buffer;
+    size_t              *lenremain;
+{
+    krb5_int32 ibuf;
+    krb5_octet         *bp;
+    size_t             remain;
+    krb5_error_code    err;
+
+    bp = *buffer;
+    remain = *lenremain;
+
+    /* Read in and check our magic number */
+    if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
+        return (EINVAL);
+
+    if (ibuf != KV5M_GSS_QUEUE)
+        return (EINVAL);
+
+    err = g_queue_internalize(argp, &bp, &remain);
+    if (err)
+        return err;
+
+    /* Read in and check our trailing magic number */
+    if (krb5_ser_unpack_int32(&ibuf, &bp, &remain)) {
+        g_order_free(argp);
+        return (EINVAL);
+    }
+
+    if (ibuf != KV5M_GSS_QUEUE) {
+        g_order_free(argp);
+        return (EINVAL);
+    }
+
+    *buffer = bp;
+    *lenremain = remain;
+    return 0;
+}
+
+static krb5_error_code
 kg_seqstate_internalize(kcontext, argp, buffer, lenremain)
     krb5_context        kcontext;
     g_seqnum_state      *argp;
@@ -208,6 +266,26 @@ kg_seqstate_internalize(kcontext, argp,
 }
 
 static krb5_error_code
+kg_queue_size(kcontext, arg, sizep)
+    krb5_context        kcontext;
+    krb5_pointer        arg;
+    size_t              *sizep;
+{
+    krb5_error_code kret;
+    size_t required;
+
+    kret = EINVAL;
+    if (arg) {
+        required = 2*sizeof(krb5_int32); /* For the header and trailer */
+        (void) g_queue_size(arg, &required);
+
+        kret = 0;
+        *sizep += required;
+    }
+    return(kret);
+}
+
+static krb5_error_code
 kg_seqstate_size(kcontext, arg, sizep)
     krb5_context        kcontext;
     g_seqnum_state      arg;
@@ -319,8 +397,9 @@ kg_ctx_size(kcontext, arg, sizep)
                                &required);
 
         if (!kret && ctx->seqstate)
-            kret = kg_seqstate_size(kcontext, ctx->seqstate, &required);
+            kret = kg_queue_size(kcontext, ctx->seqstate, &required);
 
+#if 0 /* PROVIDE_KERNEL_IMPORT */
         if (!kret)
             kret = krb5_size_opaque(kcontext,
                                     KV5M_CONTEXT,
@@ -331,11 +410,13 @@ kg_ctx_size(kcontext, arg, sizep)
                                     KV5M_AUTH_CONTEXT,
                                     (krb5_pointer) ctx->auth_context,
                                     &required);
+#endif /* PROVIDE_KERNEL_IMPORT */
         if (!kret && ctx->acceptor_subkey)
             kret = krb5_size_opaque(kcontext,
                                     KV5M_KEYBLOCK, (krb5_pointer)
                                     &ctx->acceptor_subkey->keyblock,
                                     &required);
+#if 0 /* PROVIDE_KERNEL_IMPORT */
         if (!kret && ctx->authdata) {
             krb5_int32 i;
 
@@ -358,6 +439,7 @@ kg_ctx_size(kcontext, arg, sizep)
                                         &required);
             }
         }
+#endif /* PROVIDE_KERNEL_IMPORT */
         *sizep += required;
     }
     return(kret);
@@ -400,6 +482,8 @@ kg_ctx_externalize(kcontext, arg, buffer
                                        &bp, &remain);
             (void) krb5_ser_pack_int32((krb5_int32) ctx->established,
                                        &bp, &remain);
+	    (void) krb5_ser_pack_int32((krb5_int32) ctx->big_endian,
+				       &bp, &remain);
             (void) krb5_ser_pack_int32((krb5_int32) ctx->have_acceptor_subkey,
                                        &bp, &remain);
             (void) krb5_ser_pack_int32((krb5_int32) ctx->seed_init,
@@ -467,10 +551,21 @@ kg_ctx_externalize(kcontext, arg, buffer
                                                &ctx->seq->keyblock,
                                                &bp, &remain);
 
-            if (!kret && ctx->seqstate)
-                kret = kg_seqstate_externalize(kcontext,
-                                               ctx->seqstate, &bp, &remain);
+            if (!kret && ctx->seqstate) {
+                void *q = NULL;
 
+                kret = g_order_init(&q, ctx->seq_recv,
+                                    (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0,
+                                    (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0,
+                                    ctx->proto);
+
+                if (!kret) {
+                    kret = kg_queue_externalize(kcontext, q, &bp, &remain);
+                    g_order_free(&q);
+                }
+            }
+
+#if 0 /* PROVIDE_KERNEL_IMPORT */
             if (!kret)
                 kret = krb5_externalize_opaque(kcontext,
                                                KV5M_CONTEXT,
@@ -482,6 +577,7 @@ kg_ctx_externalize(kcontext, arg, buffer
                                                KV5M_AUTH_CONTEXT,
                                                (krb5_pointer) ctx->auth_context,
                                                &bp, &remain);
+#endif /* PROVIDE_KERNEL_IMPORT */
 
             if (!kret)
                 kret = krb5_ser_pack_int32((krb5_int32) ctx->proto,
@@ -501,6 +597,7 @@ kg_ctx_externalize(kcontext, arg, buffer
             if (!kret)
                 kret = krb5_ser_pack_int32((krb5_int32) ctx->cred_rcache,
                                            &bp, &remain);
+#if 0 	/* PROVIDE_KERNEL_IMPORT */
             if (!kret) {
                 krb5_int32 i = 0;
 
@@ -534,6 +631,7 @@ kg_ctx_externalize(kcontext, arg, buffer
                                                    &remain);
                 }
             }
+#endif /* PROVIDE_KERNEL_IMPORT */
             /* trailer */
             if (!kret)
                 kret = krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain);
@@ -611,6 +709,8 @@ kg_ctx_internalize(kcontext, argp, buffe
             (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
             ctx->established = (int) ibuf;
             (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+            ctx->big_endian = (int) ibuf;
+            (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
             ctx->have_acceptor_subkey = (int) ibuf;
             (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
             ctx->seed_init = (int) ibuf;
@@ -695,12 +795,13 @@ kg_ctx_internalize(kcontext, argp, buffe
             }
 
             if (!kret) {
-                kret = kg_seqstate_internalize(kcontext, &ctx->seqstate,
+                kret = kg_queue_internalize(kcontext, &ctx->seqstate,
                                                &bp, &remain);
                 if (kret == EINVAL)
                     kret = 0;
             }
 
+#if 0 /* PROVIDE_KERNEL_IMPORT */
             if (!kret)
                 kret = krb5_internalize_opaque(kcontext,
                                                KV5M_CONTEXT,
@@ -712,10 +813,19 @@ kg_ctx_internalize(kcontext, argp, buffe
                                                KV5M_AUTH_CONTEXT,
                                                (krb5_pointer *) &ctx->auth_context,
                                                &bp, &remain);
+#endif /* PROVIDE_KERNEL_IMPORT */
 
             if (!kret)
                 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
             ctx->proto = ibuf;
+
+            if (!kret) {
+                g_order_free((void **)&(ctx->seqstate));
+                kret = g_seqstate_init(&(ctx->seqstate), ctx->seq_recv,
+                    (ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0,
+                    (ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0, ctx->proto);
+            }
+
             if (!kret)
                 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
             ctx->cksumtype = ibuf;
@@ -731,6 +841,7 @@ kg_ctx_internalize(kcontext, argp, buffe
             if (!kret)
                 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
             ctx->cred_rcache = ibuf;
+#if 0 /* PROVIDE_KERNEL_IMPORT */
             /* authdata */
             if (!kret)
                 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
@@ -769,6 +880,7 @@ kg_ctx_internalize(kcontext, argp, buffe
                         kret = 0;
                 }
             }
+#endif /* PROVIDE_KERNEL_IMPORT */
             /* Get trailer */
             if (!kret)
                 kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);