Add gss support from citi @ umich nfs-utils-1-0-6-post7-gss
authorneilbrown <neilbrown>
Tue, 19 Oct 2004 00:22:53 +0000 (00:22 +0000)
committerneilbrown <neilbrown>
Tue, 19 Oct 2004 00:22:53 +0000 (00:22 +0000)
105 files changed:
config.mk.in
configure.in
support/Makefile
support/gssapi/Makefile [new file with mode: 0644]
support/gssapi/SAMPLE_gssapi_mech.conf [new file with mode: 0644]
support/gssapi/g_accept_sec_context.c [new file with mode: 0644]
support/gssapi/g_acquire_cred.c [new file with mode: 0644]
support/gssapi/g_compare_name.c [new file with mode: 0644]
support/gssapi/g_context_time.c [new file with mode: 0644]
support/gssapi/g_delete_sec_context.c [new file with mode: 0644]
support/gssapi/g_dsp_name.c [new file with mode: 0644]
support/gssapi/g_dsp_status.c [new file with mode: 0644]
support/gssapi/g_dup_name.c [new file with mode: 0644]
support/gssapi/g_exp_sec_context.c [new file with mode: 0644]
support/gssapi/g_glue.c [new file with mode: 0644]
support/gssapi/g_imp_name.c [new file with mode: 0644]
support/gssapi/g_imp_sec_context.c [new file with mode: 0644]
support/gssapi/g_indicate_mechs.c [new file with mode: 0644]
support/gssapi/g_init_sec_context.c [new file with mode: 0644]
support/gssapi/g_initialize.c [new file with mode: 0644]
support/gssapi/g_inq_context.c [new file with mode: 0644]
support/gssapi/g_inq_cred.c [new file with mode: 0644]
support/gssapi/g_inq_names.c [new file with mode: 0644]
support/gssapi/g_mechname.c [new file with mode: 0644]
support/gssapi/g_mit_krb5_mech.c [new file with mode: 0644]
support/gssapi/g_oid_ops.c [new file with mode: 0644]
support/gssapi/g_process_context.c [new file with mode: 0644]
support/gssapi/g_rel_buffer.c [new file with mode: 0644]
support/gssapi/g_rel_cred.c [new file with mode: 0644]
support/gssapi/g_rel_name.c [new file with mode: 0644]
support/gssapi/g_rel_oid_set.c [new file with mode: 0644]
support/gssapi/g_seal.c [new file with mode: 0644]
support/gssapi/g_set_allowable_enctypes.c [new file with mode: 0644]
support/gssapi/g_sign.c [new file with mode: 0644]
support/gssapi/g_unseal.c [new file with mode: 0644]
support/gssapi/g_verify.c [new file with mode: 0644]
support/gssapi/gen_oids.c [new file with mode: 0644]
support/gssapi/gssd_pname_to_uid.c [new file with mode: 0644]
support/gssapi/mechglue.h [new file with mode: 0644]
support/gssapi/mglueP.h [new file with mode: 0644]
support/gssapi/oid_ops.c [new file with mode: 0644]
support/include/config.h.in
support/include/gssapi/gssapi.h [new file with mode: 0644]
support/lib/Makefile
support/rpc/DISCLAIMER [new file with mode: 0644]
support/rpc/Makefile [new file with mode: 0644]
support/rpc/README [new file with mode: 0644]
support/rpc/auth_gss.c [new file with mode: 0644]
support/rpc/authgss_prot.c [new file with mode: 0644]
support/rpc/include/rpc/auth.h [new file with mode: 0644]
support/rpc/include/rpc/auth_gss.h [new file with mode: 0644]
support/rpc/include/rpc/auth_unix.h [new file with mode: 0644]
support/rpc/include/rpc/clnt.h [new file with mode: 0644]
support/rpc/include/rpc/pmap_clnt.h [new file with mode: 0644]
support/rpc/include/rpc/pmap_prot.h [new file with mode: 0644]
support/rpc/include/rpc/pmap_rmt.h [new file with mode: 0644]
support/rpc/include/rpc/rpc.h [new file with mode: 0644]
support/rpc/include/rpc/rpc_des.h [new file with mode: 0644]
support/rpc/include/rpc/rpc_msg.h [new file with mode: 0644]
support/rpc/include/rpc/svc.h [new file with mode: 0644]
support/rpc/include/rpc/svc_auth.h [new file with mode: 0644]
support/rpc/include/rpc/types.h [new file with mode: 0644]
support/rpc/include/rpc/xdr.h [new file with mode: 0644]
support/rpc/rpc_commondata.c [new file with mode: 0644]
support/rpc/svc.c [new file with mode: 0644]
support/rpc/svc_auth.c [new file with mode: 0644]
support/rpc/svc_auth_gss.c [new file with mode: 0644]
support/rpc/svc_auth_none.c [new file with mode: 0644]
support/rpc/svc_auth_unix.c [new file with mode: 0644]
support/rpc/svc_raw.c [new file with mode: 0644]
support/rpc/svc_run.c [new file with mode: 0644]
support/rpc/svc_simple.c [new file with mode: 0644]
support/rpc/svc_tcp.c [new file with mode: 0644]
support/rpc/svc_udp.c [new file with mode: 0644]
utils/Makefile.in
utils/gssd/Makefile [new file with mode: 0644]
utils/gssd/context.c [new file with mode: 0644]
utils/gssd/context.h [new file with mode: 0644]
utils/gssd/context_heimdal.c [new file with mode: 0644]
utils/gssd/err_util.c [new file with mode: 0644]
utils/gssd/err_util.h [new file with mode: 0644]
utils/gssd/gss_clnt_send_err.c [new file with mode: 0644]
utils/gssd/gss_destroy_creds [new file with mode: 0644]
utils/gssd/gss_oids.c [new file with mode: 0644]
utils/gssd/gss_oids.h [new file with mode: 0644]
utils/gssd/gss_util.c [new file with mode: 0644]
utils/gssd/gss_util.h [new file with mode: 0644]
utils/gssd/gssd.c [new file with mode: 0644]
utils/gssd/gssd.h [new file with mode: 0644]
utils/gssd/gssd.man [new file with mode: 0644]
utils/gssd/gssd_main_loop.c [new file with mode: 0644]
utils/gssd/gssd_proc.c [new file with mode: 0644]
utils/gssd/krb5_util.c [new file with mode: 0644]
utils/gssd/krb5_util.h [new file with mode: 0644]
utils/gssd/write_bytes.h [new file with mode: 0644]
utils/gssdestroycreds/Makefile [new file with mode: 0644]
utils/svcgssd/Makefile [new file with mode: 0644]
utils/svcgssd/cacheio.c [new file with mode: 0644]
utils/svcgssd/cacheio.h [new file with mode: 0644]
utils/svcgssd/svcgssd.c [new file with mode: 0644]
utils/svcgssd/svcgssd.h [new file with mode: 0644]
utils/svcgssd/svcgssd.man [new file with mode: 0644]
utils/svcgssd/svcgssd_main_loop.c [new file with mode: 0644]
utils/svcgssd/svcgssd_mech2file.c [new file with mode: 0644]
utils/svcgssd/svcgssd_proc.c [new file with mode: 0644]

index 67f3d01..afbed88 100644 (file)
@@ -33,6 +33,9 @@ MANGROUP      = root
 LIBBSD         = @LIBBSD@
 LIBNSL         = @LIBNSL@
 LIBWRAP                = @LIBWRAP@
+KRBLIB         = @KRBLIB@
+KRBDIR         = @KRBDIR@
+KRB5_VERSION   = @K5VERS@
 
 ################# END OF USER SERVICEABLE PARTS ##################
 ALLTARGETS     = all clean distclean install installman \
@@ -58,6 +61,7 @@ INSTALL               = install
 MAN2PS         = groff -Tps -man
 
 AFLAGS         = -I$(TOP)support/include \
+                 -I$(KRBDIR)/include \
                  -Wall $(ARCHFLAGS) -pipe
 ifdef KERNEL_INCDIR
 AFLAGS        += -I$(KERNEL_INCDIR)
index 93588c2..4962197 100644 (file)
@@ -52,6 +52,22 @@ AC_ARG_ENABLE(nfsv4,
        fi
        AC_SUBST(IDMAPD)
        AC_SUBST(enable_nfsv4)
+AC_ARG_ENABLE(gss,
+       [  --enable-gss           enable support for rpcsec_gss],
+       enable_gss=$enableval,
+       enable_gss=yes)
+       if test "$enable_gss" = yes; then
+               AC_DEFINE(GSS_SUPPORTED)
+               GSSD=gssd
+               SVCGSSD=svcgssd
+       else
+               enable_gss=
+               GSSD=
+               SVCGSSD=
+       fi
+       AC_SUBST(GSSD)
+       AC_SUBST(SVCGSSD)
+       AC_SUBST(enable_gss)
 AC_ARG_ENABLE(kprefix,
        [  --enable-kprefix       install progs as rpc.knfsd etc],
        test "$enableval" = "yes" && kprefix=k,
@@ -117,6 +133,94 @@ AC_SUBST(LIBBSD)
 AC_TCP_WRAPPER
 AC_SUBST(LIBWRAP)
 
+if test "$enable_gss" = yes; then
+  dnl Checks for Kerberos
+  dnl NOTE: while we intend to do generic gss-api, currently we
+  dnl have a requirement to get an initial Kerberos machine
+  dnl credential.  Thus, the requirement for Kerberos.
+  dnl The Kerberos gssapi library will be dynamically loaded?
+  AC_MSG_CHECKING(for Kerberos v5)
+  AC_ARG_WITH(krb5,
+  [  --with-krb5=DIR         use Kerberos v5 installation in DIR],
+  [ case "$withval" in
+    yes|no)
+       krb5_with=""
+       ;;
+    *)
+       krb5_with="$withval"
+       ;;
+    esac ]
+  )
+
+  for dir in $krb5_with /usr/kerberos /usr/local /usr/local/krb5 /usr/krb5 \
+             /usr/heimdal /usr/local/heimdal /usr/athena /usr ; do
+    dnl This ugly hack brought on by the split installation of
+    dnl MIT Kerberos on Fedora Core 1
+    K5CONFIG=""
+    if test -f $dir/bin/krb5-config; then
+      K5CONFIG=$dir/bin/krb5-config
+    elif test -f "/usr/kerberos/bin/krb5-config"; then
+      K5CONFIG="/usr/kerberos/bin/krb5-config"
+    fi
+    if test "$K5CONFIG" != ""; then
+      if test -f $dir/include/gssapi/gssapi_krb5.h -a \
+              \( -f $dir/lib/libgssapi_krb5.a -o \
+           -f $dir/lib/libgssapi_krb5.so \) ; then
+         AC_DEFINE(HAVE_KRB5)
+         KRBDIR="$dir"
+         K5VERS=`$K5CONFIG --version | awk '{split($4,v,"."); print v[[1]]v[[2]]v[[3]] }'`
+         AC_DEFINE_UNQUOTED(KRB5_VERSION,$K5VERS)
+         KRBLIB=`$K5CONFIG --libs gssapi`
+         if test $K5VERS -le 131; then
+           AC_DEFINE(USE_PRIVATE_KRB5_FUNCTIONS)
+         fi
+         AC_CHECK_LIB(gssapi_krb5, gss_krb5_export_lucid_sec_context,
+           AC_DEFINE(HAVE_LUCID_CONTEXT_SUPPORT),,$KRBLIB)
+         AC_CHECK_LIB(gssapi_krb5, gss_krb5_set_allowable_enctypes,
+           AC_DEFINE(HAVE_SET_ALLOWABLE_ENCTYPES),,$KRBLIB)
+         AC_CHECK_LIB(gssapi_krb5, gss_krb5_ccache_name,
+           AC_DEFINE(HAVE_GSS_KRB5_CCACHE_NAME),,$KRBLIB)
+         break
+      dnl The following ugly hack brought on by the split installation
+      dnl of Heimdal Kerberos on SuSe
+      elif test \( -f $dir/include/heim_err.h -o\
+                -f $dir/include/heimdal/heim_err.h \) -a \
+                -f $dir/lib/libroken.a; then
+         AC_DEFINE(HAVE_HEIMDAL)
+         KRBDIR="$dir"
+         K5VERS=`$K5CONFIG --version | head -1 | awk '{split($2,v,"."); print v[[1]]v[[2]]v[[3]] }'`
+         AC_DEFINE_UNQUOTED(KRB5_VERSION,$K5VERS)
+         KRBLIB=`$K5CONFIG --libs gssapi`
+         AC_CHECK_LIB(gssapi, gss_krb5_export_lucid_sec_context,
+           AC_DEFINE(HAVE_LUCID_CONTEXT_SUPPORT),,$KRBLIB)
+         AC_CHECK_LIB(gssapi, gss_krb5_set_allowable_enctypes,
+           AC_DEFINE(HAVE_SET_ALLOWABLE_ENCTYPES),,$KRBLIB)
+         AC_CHECK_LIB(gssapi, gss_krb5_ccache_name,
+           AC_DEFINE(HAVE_GSS_KRB5_CCACHE_NAME),,$KRBLIB)
+        break
+      fi
+      CFLAGS=$CFLAGS `K5CONFIG --cflags`
+    fi
+  done
+  dnl We didn't find a usable Kerberos environment
+  if test "x$KRBDIR" = "x"; then
+    if test "x$krb5_with" = "x"; then
+      AC_MSG_ERROR(Kerberos v5 with GSS support not found)
+    else
+      AC_MSG_ERROR(Kerberos v5 with GSS support not found at $krb5_with)
+    fi
+  fi
+  AC_MSG_RESULT($KRBDIR)
+  dnl If they specified a directory and it didn't work, give them a warning
+  if test "x$krb5_with" != "x" -a "$krb5_with" != "$KRBDIR"; then
+    AC_MSG_WARN(Using $KRBDIR instead of requested value of $krb5_with for Kerberos!)
+  fi
+
+  AC_SUBST([KRBDIR])
+  AC_SUBST([KRBLIB])
+  AC_SUBST([K5VERS])
+fi
+
 dnl *************************************************************
 dnl Check for headers
 dnl *************************************************************
index 37b6359..aa56fa7 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for linux-nfs/support
 #
 
-SUBDIRS        = include nfs export lib misc
+SUBDIRS        = include nfs export lib misc rpc gssapi
 .DEFAULT: all
 
 include $(TOP)rules.mk
diff --git a/support/gssapi/Makefile b/support/gssapi/Makefile
new file mode 100644 (file)
index 0000000..65271f0
--- /dev/null
@@ -0,0 +1,24 @@
+#
+# libgssapi.a
+# gssapi mechanism-switching layer
+#
+
+LIBNAME        = libgssapi.a
+SRCS   = g_accept_sec_context.c g_acquire_cred.c g_compare_name.c \
+       g_context_time.c g_delete_sec_context.c g_dsp_name.c g_dsp_status.c \
+       g_dup_name.c gen_oids.c g_exp_sec_context.c g_glue.c g_imp_name.c \
+       g_imp_sec_context.c g_indicate_mechs.c g_initialize.c \
+       g_init_sec_context.c g_inq_context.c g_inq_cred.c g_inq_names.c \
+       g_mechname.c g_mit_krb5_mech.c g_oid_ops.c g_process_context.c \
+       g_rel_buffer.c g_rel_cred.c g_rel_name.c g_rel_oid_set.c g_seal.c \
+       g_sign.c gssd_pname_to_uid.c g_unseal.c g_verify.c oid_ops.c \
+       g_set_allowable_enctypes.c
+
+OBJS   = $(SRCS:.c=.o)
+
+include $(TOP)rules.mk
+
+CFLAGS += -DKRB5_VERSION=$(KRB5_VERSION) -I$(TOP)/support/include
+
+install::
+       @:
diff --git a/support/gssapi/SAMPLE_gssapi_mech.conf b/support/gssapi/SAMPLE_gssapi_mech.conf
new file mode 100644 (file)
index 0000000..8eca824
--- /dev/null
@@ -0,0 +1,19 @@
+# GSSAPI Mechanism Definitions
+#
+# This configuration file determines which GSS-API mechanisms
+# the gssd code should use
+#
+# NOTE:
+# The initiaiization function "mechglue_internal_krb5_init"
+# is used for the MIT krb5 gssapi mechanism.  This special
+# function name indicates that an internal function should
+# be used to determine the entry points for the MIT gssapi
+# mechanism funtions.
+#
+# library                               initialization function
+# ================================     ==========================
+# The MIT K5 gssapi library, use special function for initialization.
+/usr/lib/libgssapi_krb5.so     mechglue_internal_krb5_init
+#
+# The SPKM3 gssapi library function.  Use the function spkm3_gss_initialize.
+# /usr/local/gss_mechs/spkm/spkm3/libgssapi_spkm3.so    spkm3_gss_initialize
diff --git a/support/gssapi/g_accept_sec_context.c b/support/gssapi/g_accept_sec_context.c
new file mode 100644 (file)
index 0000000..05e967b
--- /dev/null
@@ -0,0 +1,213 @@
+/* #ident  "@(#)gss_accept_sec_context.c 1.19     95/08/07 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_accept_sec_context
+ */
+
+#include "mglueP.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+OM_uint32 KRB5_CALLCONV
+gss_accept_sec_context (minor_status,
+                        context_handle,
+                        verifier_cred_handle,
+                        input_token_buffer,
+                        input_chan_bindings,
+                        src_name,
+                        mech_type,
+                        output_token,
+                        ret_flags,
+                        time_rec,
+                        delegated_cred_handle)
+
+OM_uint32 *            minor_status;
+gss_ctx_id_t *         context_handle;
+gss_cred_id_t          verifier_cred_handle;
+gss_buffer_t           input_token_buffer;
+gss_channel_bindings_t input_chan_bindings;
+gss_name_t *           src_name;
+gss_OID *              mech_type;
+gss_buffer_t           output_token;
+OM_uint32 *            ret_flags;
+OM_uint32 *            time_rec;
+gss_cred_id_t *                delegated_cred_handle;
+
+{
+    OM_uint32          status, temp_status, temp_minor_status;
+    gss_union_ctx_id_t union_ctx_id;
+    gss_union_cred_t   union_cred;
+    gss_cred_id_t      input_cred_handle = GSS_C_NO_CREDENTIAL;
+    gss_name_t         internal_name;
+    gss_OID_desc       token_mech_type_desc;
+    gss_OID            token_mech_type = &token_mech_type_desc;
+    gss_mechanism      mech;
+
+    gss_initialize();
+
+    if (context_handle == NULL)
+       return GSS_S_NO_CONTEXT;
+
+    /*
+     * if context_handle is GSS_C_NO_CONTEXT, allocate a union context
+     * descriptor to hold the mech type information as well as the
+     * underlying mechanism context handle. Otherwise, cast the
+     * value of *context_handle to the union context variable.
+     */
+
+    if(*context_handle == GSS_C_NO_CONTEXT) {
+
+       /* Get the token mech type */
+       status = __gss_get_mech_type(token_mech_type, input_token_buffer);
+       if (status)
+           return status;
+
+       status = GSS_S_FAILURE;
+       union_ctx_id = (gss_union_ctx_id_t)
+           malloc(sizeof(gss_union_ctx_id_desc));
+       if (!union_ctx_id) {
+           *minor_status = ENOMEM;
+           goto error_out;
+       }
+
+       union_ctx_id->mech_type = (gss_OID) malloc(sizeof(gss_OID_desc));
+       if (!union_ctx_id->mech_type) {
+           *minor_status = ENOMEM;
+           goto error_out;
+       }
+
+       union_ctx_id->mech_type->elements = (void *)
+           malloc(token_mech_type->length);
+       if (!union_ctx_id->mech_type->elements) {
+           *minor_status = ENOMEM;
+           goto error_out;
+       }
+
+       union_ctx_id->mech_type->length = token_mech_type->length;
+       memcpy(union_ctx_id->mech_type->elements,
+              token_mech_type->elements,
+              token_mech_type->length);
+
+       /* copy the supplied context handle */
+
+       union_ctx_id->internal_ctx_id = *context_handle;
+    } else {
+       union_ctx_id = *context_handle;
+       token_mech_type = union_ctx_id->mech_type;
+    }
+
+    /*
+     * get the appropriate cred handle from the union cred struct.
+     * defaults to GSS_C_NO_CREDENTIAL if there is no cred, which will
+     * use the default credential.
+     */
+    union_cred = (gss_union_cred_t) verifier_cred_handle;
+    input_cred_handle = __gss_get_mechanism_cred(union_cred, token_mech_type);
+
+    /*
+     * now select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    mech = __gss_get_mechanism (token_mech_type);
+    if (mech && mech->gss_accept_sec_context) {
+
+           status = mech->gss_accept_sec_context(
+#ifdef USE_MECH_CONTEXT
+                                                 mech->context,
+#endif
+                                                 minor_status,
+                                                 &union_ctx_id->internal_ctx_id,
+                                                 input_cred_handle,
+                                                 input_token_buffer,
+                                                 input_chan_bindings,
+                                                 &internal_name,
+                                                 mech_type,
+                                                 output_token,
+                                                 ret_flags,
+                                                 time_rec,
+                                                 delegated_cred_handle);
+
+           /* If there's more work to do, keep going... */
+           if (status == GSS_S_CONTINUE_NEEDED)
+               return GSS_S_CONTINUE_NEEDED;
+
+           /* if the call failed, return with failure */
+           if (status != GSS_S_COMPLETE)
+               goto error_out;
+
+           /*
+            * if src_name is non-NULL,
+            * convert internal_name into a union name equivalent
+            * First call the mechanism specific display_name()
+            * then call gss_import_name() to create
+            * the union name struct cast to src_name
+            */
+#if 0
+           /* ANDROS: src_name is never null, it is a ptr from the gss_accept_sec_context
+            * caller.  internal_name may or may not be set by the mechanism. so, don't
+            * call __gss_convert_name_to_union_name which sets the src_name
+            * unless the internal name is set
+            * by the above mech->gss_accept_sec_context.
+            */
+           if (internal_name != NULL && status == GSS_S_COMPLETE) {
+#else
+           if (src_name != NULL && status == GSS_S_COMPLETE) {
+#endif
+               temp_status = __gss_convert_name_to_union_name(
+                      &temp_minor_status, mech, internal_name, src_name);
+               if (temp_status != GSS_S_COMPLETE) {
+                   if (minor_status)
+                       *minor_status = temp_minor_status;
+                   gss_release_buffer(&temp_minor_status, output_token);
+                   __gss_release_internal_name(&temp_minor_status,
+                                         &mech->mech_type, &internal_name);
+                   return (temp_status);
+               }
+           }
+
+       if(*context_handle == GSS_C_NO_CONTEXT)
+           *context_handle = (gss_ctx_id_t *) union_ctx_id;
+
+       return(status);
+    }
+
+    return(GSS_S_BAD_MECH);
+
+error_out:
+    if (union_ctx_id) {
+       if (union_ctx_id->mech_type) {
+           if (union_ctx_id->mech_type->elements)
+               free(union_ctx_id->mech_type->elements);
+           free(union_ctx_id->mech_type);
+       }
+       free(union_ctx_id);
+    }
+    return (status);
+}
+
diff --git a/support/gssapi/g_acquire_cred.c b/support/gssapi/g_acquire_cred.c
new file mode 100644 (file)
index 0000000..50087db
--- /dev/null
@@ -0,0 +1,539 @@
+/* #ident  "@(#)gss_acquire_cred.c 1.19     95/08/07 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_acquire_cred
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+#define g_OID_equal(o1,o2) \
+   (((o1)->length == (o2)->length) && \
+    (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0))
+
+static gss_OID_set
+create_actual_mechs(creds)
+    gss_union_cred_t   creds;
+{
+    gss_OID_set        actual_mechs;
+    int                        i;
+
+    actual_mechs = (gss_OID_set) malloc(sizeof(gss_OID_set_desc));
+    if (!actual_mechs)
+       return NULL;
+
+    actual_mechs->elements = (gss_OID)
+           malloc(sizeof(gss_OID_desc) * creds->count);
+    if (!actual_mechs->elements) {
+       free(actual_mechs);
+       return NULL;
+    }
+
+    actual_mechs->count = creds->count;
+
+    for (i=0; i < creds->count; i++) {
+       actual_mechs->elements[i].length = creds->mechs_array[i].length;
+       actual_mechs->elements[i].elements = (void *)
+           malloc(creds->mechs_array[i].length);
+       memcpy(actual_mechs->elements[i].elements,
+              creds->mechs_array[i].elements, creds->mechs_array[i].length);
+    }
+
+    return actual_mechs;
+}
+
+
+OM_uint32 KRB5_CALLCONV
+gss_acquire_cred(minor_status,
+                 desired_name,
+                 time_req,
+                 desired_mechs,
+                cred_usage,
+                 output_cred_handle,
+                 actual_mechs,
+                 time_rec)
+
+OM_uint32 *            minor_status;
+gss_name_t             desired_name;
+OM_uint32              time_req;
+gss_OID_set            desired_mechs;
+int                    cred_usage;
+gss_cred_id_t *                output_cred_handle;
+gss_OID_set *          actual_mechs;
+OM_uint32 *            time_rec;
+
+{
+    OM_uint32          status, temp_minor_status, temp_time_rec = ~0;
+    unsigned int       i, j, creds_acquired = 0;
+    int                        k;
+    gss_union_name_t   union_name;
+    gss_name_t         internal_name;
+    gss_union_cred_t   creds;
+    gss_OID_set_desc   default_OID_set;
+    gss_OID_desc       default_OID;
+    gss_OID            specific_mech_type = 0;
+    gss_mechanism      mech;
+
+    /*
+     * This struct is used to keep track of which mech_types are
+     * actually available and to store the credentials returned
+     * from them by each mechanism specific gss_acquire_cred() call.
+     * The results are used to construct the final union_cred
+     * structure returned by the glue layer gss_acquire_cred() call
+     * and the actual_mechs gss_OID_set returned.
+     */
+
+    struct creds_returned {
+       unsigned char   available;
+       gss_cred_id_t   cred;
+    } *creds_returned;
+
+    gss_initialize();
+
+    /* Set this to NULL for now */
+
+    if (actual_mechs)
+       *actual_mechs = GSS_C_NULL_OID_SET;
+
+    if (minor_status)
+       *minor_status = 0;
+
+    /* No need to continue if we don't have a place to store the creds */
+    if (output_cred_handle == NULL)
+       return GSS_S_COMPLETE;
+
+    /* get desired_name cast as a union_name type */
+
+    union_name = (gss_union_name_t) desired_name;
+
+    if (union_name)
+           specific_mech_type = union_name->mech_type;
+
+    /*
+     * if desired_mechs equals GSS_C_NULL_OID_SET, then pick an
+     * appropriate default.
+     */
+    if(desired_mechs == GSS_C_NULL_OID_SET) {
+       /*
+        * If union_name->mech_type is NULL then we get the default
+        * mechanism; otherwise, we get the mechanism for the
+        * mechanism-specific name.
+        */
+       mech = __gss_get_mechanism(specific_mech_type);
+       if (mech == NULL)
+           return (GSS_S_BAD_MECH);
+
+       desired_mechs = &default_OID_set;
+       default_OID_set.count = 1 ;
+       default_OID_set.elements = &default_OID;
+       default_OID.length = mech->mech_type.length;
+       default_OID.elements = mech->mech_type.elements;
+    }
+
+    /*
+     * Now allocate the creds returned array. There is one element
+     * for each member of the desired_mechs argument.
+     */
+
+    creds_returned = (struct creds_returned *)
+       malloc(sizeof(struct creds_returned) * desired_mechs->count);
+
+    /*
+     * For each requested mechanism in desired_mechs, determine if it
+     * is supported. If so, mark the corresponding element in
+     * creds_returned->available as 1 and call the mechanism
+     * specific gss_acquire_cred(), placing the returned cred in
+     * creds_returned->cred. If not, mark creds_returned->available as
+     * 0.
+     */
+    status = GSS_S_BAD_MECH;
+    for (j=0; j < desired_mechs->count; j++) {
+       creds_returned[j].available = 0;
+
+       mech = __gss_get_mechanism (&desired_mechs->elements[j]);
+       if (!mech || !mech->gss_acquire_cred)
+           continue;
+       /*
+        * If this is a mechanism-specific name, then only use the
+        * mechanism of the name.
+        */
+       if (specific_mech_type && !g_OID_equal(specific_mech_type,
+                                              &mech->mech_type))
+           continue;
+       /*
+        * If this is not a mechanism-specific name, then we need to
+        * do an import the external name in union_name first.
+        */
+       if (union_name == 0)
+           internal_name = (gss_name_t) 0;
+       else if (!union_name->mech_type) {
+           if (__gss_import_internal_name(&temp_minor_status,
+                                          &mech->mech_type,
+                                          union_name, &internal_name)) {
+               continue;
+           }
+       } else
+           internal_name = union_name->mech_name;
+
+#ifdef USE_MECH_CONTEXT
+       status = mech->gss_acquire_cred(mech->context, minor_status,
+#else
+       status = mech->gss_acquire_cred(minor_status,
+#endif
+                                       internal_name, time_req,
+                                       desired_mechs, cred_usage,
+                                       &creds_returned[j].cred,
+                                       NULL, &temp_time_rec);
+
+       /* Release the internal name, if allocated above */
+       if (union_name && !union_name->mech_type) {
+           (void) __gss_release_internal_name(&temp_minor_status,
+                                              &mech->mech_type,
+                                              &internal_name);
+       }
+
+       if (status != GSS_S_COMPLETE)
+           continue;
+
+       /*
+        * Add this into the creds_returned structure, if we got
+        * a good credential for this mechanism.
+        */
+       if (time_rec) {
+           *time_rec = *time_rec > temp_time_rec ? temp_time_rec : *time_rec;
+           temp_time_rec = *time_rec;
+       }
+
+       creds_returned[j].available = 1;
+       creds_acquired++;
+
+       /*
+        * If union_name is set, then we're done.  Continue, and
+        * declare success.  Otherwise, if do an inquire credentials
+        * from the first mechanism that succeeds and use that as the
+        * union name.
+        */
+       if (union_name)
+           continue;
+
+#ifdef USE_MECH_CONTEXT
+       status = mech->gss_inquire_cred(mech->context, &temp_minor_status,
+#else
+       status = mech->gss_inquire_cred(&temp_minor_status,
+#endif
+                                       creds_returned[j].cred,
+                                       &internal_name, 0, 0, 0);
+       if (status) {
+           /* Should never happen */
+           creds_returned[j].available = 0;
+           creds_acquired--;
+           if (mech->gss_release_cred)
+#ifdef USE_MECH_CONTEXT
+               mech->gss_release_cred(mech->context, minor_status,
+#else
+               mech->gss_release_cred(minor_status,
+#endif
+                                      &creds_returned[j].cred);
+           continue;
+       }
+
+       status = __gss_convert_name_to_union_name(&temp_minor_status, mech,
+                                                 internal_name,
+                                                 (gss_name_t *) &union_name);
+    }
+
+    /*
+     * Now allocate the creds struct, which will be cast as a gss_cred_id_t
+     * and returned in the output_cred_handle argument. If there were
+     * no credentials found, return an error. Also, allocate the
+     * actual_mechs data.
+     */
+    if (creds_acquired == 0) {
+       free (creds_returned);
+       return (status);
+    }
+
+    creds = (gss_union_cred_t) malloc(sizeof(gss_union_cred_desc));
+
+    creds->count = creds_acquired;
+
+    creds->mechs_array = (gss_OID)
+       malloc(sizeof(gss_OID_desc) * creds_acquired);
+
+    creds->cred_array = (gss_cred_id_t *)
+       malloc(sizeof(gss_cred_id_t) * creds_acquired);
+
+    if(actual_mechs != NULL) {
+       *actual_mechs = (gss_OID_set) malloc(sizeof(gss_OID_set_desc));
+
+       (*actual_mechs)->count = creds_acquired;
+
+       (*actual_mechs)->elements = (gss_OID)
+           malloc(sizeof(gss_OID_desc) * creds_acquired);
+    }
+
+    /*
+     * copy the mechanisms found and their allocated credentials into the
+     * creds structure. At the same time, build up the actual_mechs
+     * data.
+     */
+
+    j = 0;
+
+    for (i=0; i<desired_mechs->count; i++) {
+       if(creds_returned[i].available) {
+
+           creds->mechs_array[j].length =
+               desired_mechs->elements[i].length;
+           creds->mechs_array[j].elements = (void *)
+               malloc(desired_mechs->elements[i].length);
+           memcpy(creds->mechs_array[j].elements,
+                  desired_mechs->elements[i].elements,
+                  desired_mechs->elements[i].length);
+           creds->cred_array[j] = creds_returned[i].cred;
+           if (actual_mechs) {
+                   (*actual_mechs)->elements[j].length =
+                       desired_mechs->elements[i].length;
+                   (*actual_mechs)->elements[j].elements = (void *)
+                       malloc(desired_mechs->elements[i].length);
+                   memcpy((*actual_mechs)->elements[j].elements,
+                          desired_mechs->elements[i].elements,
+                          desired_mechs->elements[i].length);
+           }
+           j++;
+       }
+    }
+
+    /* free the creds_returned struct, since we are done with it. */
+
+    free(creds_returned);
+
+    /* record the information needed for gss_inquire_cred() */
+
+    creds->auxinfo.creation_time = time(0);
+    creds->auxinfo.time_rec = temp_time_rec;
+    creds->auxinfo.cred_usage =  cred_usage;
+
+    /*
+     * we can't just record the internal name, desired_name, since
+     * it may be destroyed between now and the time gss_inquire_cred()
+     * is called.  So we must record the printable name in a
+     * gss_buffer_t, calling gss_display_name() to fill it in. When
+     * gss_inquire_name() is called, we must then call gss_import_name()
+     * to get the internal name that is required at that point.
+     */
+    if (desired_name) {
+       status = gss_display_name(&temp_minor_status, desired_name,
+                                 &creds->auxinfo.name,
+                                 &creds->auxinfo.name_type);
+       if (status) {
+           status = GSS_S_BAD_NAME;
+           goto error_out;
+       }
+    } else {
+       status = gss_display_name(&temp_minor_status, union_name,
+                                 &creds->auxinfo.name,
+                                 &creds->auxinfo.name_type);
+       if (status) {
+           status = GSS_S_BAD_NAME;
+           goto error_out;
+       }
+    }
+
+    *output_cred_handle = (gss_cred_id_t) creds;
+    return(GSS_S_COMPLETE);
+
+error_out:
+    for (k=0; k < creds->count; k++) {
+       free(creds->mechs_array[k].elements);
+       if (actual_mechs)
+           free((*actual_mechs)->elements[k].elements);
+    }
+
+    if (actual_mechs) {
+       free((*actual_mechs)->elements);
+       free(*actual_mechs);
+       *actual_mechs = GSS_C_NULL_OID_SET;
+    }
+    free(creds->cred_array);
+    free(creds->mechs_array);
+    free(creds);
+
+    return(status);
+}
+
+/* V2 KRB5_CALLCONV */
+OM_uint32 KRB5_CALLCONV
+gss_add_cred(minor_status, input_cred_handle,
+                 desired_name, desired_mech, cred_usage,
+                 initiator_time_req, acceptor_time_req,
+                 output_cred_handle, actual_mechs,
+                 initiator_time_rec, acceptor_time_rec)
+    OM_uint32          *minor_status;
+    gss_cred_id_t      input_cred_handle;
+    gss_name_t         desired_name;
+    gss_OID            desired_mech;
+    gss_cred_usage_t   cred_usage;
+    OM_uint32          initiator_time_req;
+    OM_uint32          acceptor_time_req;
+    gss_cred_id_t      *output_cred_handle;
+    gss_OID_set                *actual_mechs;
+    OM_uint32          *initiator_time_rec;
+    OM_uint32          *acceptor_time_rec;
+{
+    OM_uint32          status, temp_minor_status;
+    OM_uint32          time_req, time_rec;
+    gss_union_name_t   union_name;
+    gss_union_cred_t   new_union_cred, union_cred;
+    gss_name_t         internal_name;
+    gss_mechanism      mech;
+    gss_cred_id_t      cred;
+    gss_OID            new_mechs_array;
+    gss_cred_id_t *    new_cred_array;
+
+    if (input_cred_handle == GSS_C_NO_CREDENTIAL)
+       return GSS_S_NO_CRED;
+
+    union_cred = (gss_union_cred_t) input_cred_handle;
+
+    mech = __gss_get_mechanism(desired_mech);
+    if (!mech)
+       return GSS_S_BAD_MECH;
+
+    if (__gss_get_mechanism_cred(union_cred, desired_mech) !=
+       GSS_C_NO_CREDENTIAL)
+       return GSS_S_DUPLICATE_ELEMENT;
+
+    union_name = (gss_union_name_t) desired_name;
+    if (union_name->mech_type) {
+       if (!g_OID_equal(desired_mech, union_name->mech_type))
+           return GSS_S_BAD_NAMETYPE;
+       internal_name = union_name->mech_name;
+    } else {
+       if (__gss_import_internal_name(minor_status, desired_mech,
+                                      union_name, &internal_name))
+           return (GSS_S_BAD_NAME);
+    }
+
+    if (cred_usage == GSS_C_ACCEPT)
+       time_req = acceptor_time_req;
+    else if (cred_usage == GSS_C_INITIATE)
+       time_req = initiator_time_req;
+    else if (cred_usage == GSS_C_BOTH)
+       time_req = (acceptor_time_req > initiator_time_req) ?
+           acceptor_time_req : initiator_time_req;
+
+#ifdef USE_MECH_CONTEXT
+    status = mech->gss_acquire_cred(mech->context, minor_status,
+#else
+    status = mech->gss_acquire_cred(minor_status,
+#endif
+                                   internal_name, time_req,
+                                   GSS_C_NULL_OID_SET, cred_usage,
+                                   &cred, NULL, &time_rec);
+    if (status != GSS_S_COMPLETE)
+       goto errout;
+
+    new_mechs_array = (gss_OID)
+       malloc(sizeof(gss_OID_desc) * (union_cred->count+1));
+
+    new_cred_array = (gss_cred_id_t *)
+       malloc(sizeof(gss_cred_id_t) * (union_cred->count+1));
+
+    if (!new_mechs_array || !new_cred_array) {
+       *minor_status = ENOMEM;
+       status = GSS_S_FAILURE;
+       goto errout;
+    }
+
+
+    if (acceptor_time_rec)
+       if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH)
+           *acceptor_time_rec = time_rec;
+    if (initiator_time_rec)
+       if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH)
+           *initiator_time_rec = time_rec;
+
+    /*
+     * OK, expand the mechanism array in the union credentials
+     * (Look for the union label...)
+     */
+    memcpy(new_mechs_array, union_cred->mechs_array,
+          sizeof(gss_OID_desc) * union_cred->count);
+    memcpy(new_cred_array, union_cred->cred_array,
+          sizeof(gss_cred_id_t) * union_cred->count);
+
+    new_cred_array[union_cred->count] = cred;
+    new_mechs_array[union_cred->count].length = desired_mech->length;
+    new_mechs_array[union_cred->count].elements = malloc(desired_mech->length);
+    if (!new_mechs_array[union_cred->count].elements) {
+       *minor_status = ENOMEM;
+       goto errout;
+    }
+    memcpy(new_mechs_array[union_cred->count].elements, desired_mech->elements,
+          desired_mech->length);
+
+    if (output_cred_handle == NULL) {
+       free(union_cred->mechs_array);
+       free(union_cred->cred_array);
+       new_union_cred = union_cred;
+    } else {
+       new_union_cred = malloc(sizeof(gss_union_cred_desc));
+       if (new_union_cred == NULL) {
+           *minor_status = ENOMEM;
+           goto errout;
+       }
+       *new_union_cred = *union_cred;
+       *output_cred_handle = new_union_cred;
+    }
+    new_union_cred->mechs_array = new_mechs_array;
+    new_union_cred->cred_array = new_cred_array;
+    new_union_cred->count++;
+    new_mechs_array = 0;
+    new_cred_array = 0;
+
+    if (actual_mechs)
+       *actual_mechs = create_actual_mechs(new_union_cred);
+
+    status = GSS_S_COMPLETE;
+
+errout:
+    if (new_mechs_array)
+       free(new_mechs_array);
+    if (new_cred_array)
+       free(new_cred_array);
+    if (!union_name->mech_type) {
+       (void) __gss_release_internal_name(&temp_minor_status,
+                                          desired_mech, &internal_name);
+    }
+
+    return(status);
+}
diff --git a/support/gssapi/g_compare_name.c b/support/gssapi/g_compare_name.c
new file mode 100644 (file)
index 0000000..496d497
--- /dev/null
@@ -0,0 +1,165 @@
+/* #ident  "@(#)gss_compare_name.c 1.13     95/08/02 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_compare_name
+ *
+ */
+
+#include "mglueP.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+#define g_OID_equal(o1,o2) \
+   (((o1)->length == (o2)->length) && \
+    (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0))
+
+OM_uint32 KRB5_CALLCONV
+gss_compare_name (minor_status,
+                  name1,
+                  name2,
+                  name_equal)
+
+OM_uint32 *            minor_status;
+gss_name_t             name1;
+gss_name_t             name2;
+int *                  name_equal;
+
+{
+    OM_uint32          major_status, temp_minor;
+    gss_union_name_t   union_name1, union_name2;
+    gss_mechanism      mech;
+    gss_name_t         internal_name;
+
+    gss_initialize();
+
+    if (name1 == 0 || name2 == 0) {
+       if (name_equal)
+           *name_equal = 0;
+       return GSS_S_BAD_NAME;
+    }
+
+    union_name1 = (gss_union_name_t) name1;
+    union_name2 = (gss_union_name_t) name2;
+    /*
+     * Try our hardest to make union_name1 be the mechanism-specific
+     * name.  (Of course we can't if both names aren't
+     * mechanism-specific.)
+     */
+    if (union_name1->mech_type == 0) {
+       union_name1 = (gss_union_name_t) name2;
+       union_name2 = (gss_union_name_t) name1;
+    }
+    /*
+     * If union_name1 is mechanism specific, then fetch its mechanism
+     * information.
+     */
+    if (union_name1->mech_type) {
+       mech = __gss_get_mechanism (union_name1->mech_type);
+       if (!mech)
+           return (GSS_S_BAD_MECH);
+       if (!mech->gss_compare_name)
+           return (GSS_S_BAD_BINDINGS);
+    }
+
+    if (name_equal == NULL)
+       return GSS_S_COMPLETE;
+
+    *name_equal = 0;           /* Default to *not* equal.... */
+
+    /*
+     * First case... both names are mechanism-specific
+     */
+    if (union_name1->mech_type && union_name2->mech_type) {
+       if (!g_OID_equal(union_name1->mech_type, union_name2->mech_type))
+           return (GSS_S_COMPLETE);
+       if ((union_name1->mech_name == 0) || (union_name2->mech_name == 0))
+           /* should never happen */
+           return (GSS_S_BAD_NAME);
+#ifdef USE_MECH_CONTEXT
+       return (mech->gss_compare_name(mech->context, minor_status,
+#else
+       return (mech->gss_compare_name(minor_status,
+#endif
+                                      union_name1->mech_name,
+                                      union_name2->mech_name, name_equal));
+
+    }
+
+    /*
+     * Second case... both names are NOT mechanism specific.
+     *
+     * All we do here is make sure the two name_types are equal and then
+     * that the external_names are equal. Note the we do not take care
+     * of the case where two different external names map to the same
+     * internal name. We cannot determine this, since we as yet do not
+     * know what mechanism to use for calling the underlying
+     * gss_import_name().
+     */
+    if (!union_name1->mech_type && !union_name2->mech_type) {
+       if (!g_OID_equal(union_name1->name_type, union_name2->name_type))
+           return (GSS_S_COMPLETE);
+       if ((union_name1->external_name->length !=
+            union_name2->external_name->length) ||
+           (memcmp(union_name1->external_name->value,
+                   union_name2->external_name->value,
+                   union_name1->external_name->length) != 0))
+           return (GSS_S_COMPLETE);
+       *name_equal = 1;
+       return (GSS_S_COMPLETE);
+    }
+
+    /*
+     * Final case... one name is mechanism specific, the other isn't.
+     *
+     * We attempt to convert the general name to the mechanism type of
+     * the mechanism-specific name, and then do the compare.  If we
+     * can't import the general name, then we return that the name is
+     * _NOT_ equal.
+     */
+    if (union_name2->mech_type) {
+       /* We make union_name1 the mechanism specific name. */
+       union_name1 = (gss_union_name_t) name2;
+       union_name2 = (gss_union_name_t) name1;
+    }
+    major_status = __gss_import_internal_name(minor_status,
+                                             union_name1->mech_type,
+                                             union_name2,
+                                             &internal_name);
+    if (major_status != GSS_S_COMPLETE)
+       return (GSS_S_COMPLETE);
+#ifdef USE_MECH_CONTEXT
+    major_status = mech->gss_compare_name(mech->context, minor_status,
+#else
+    major_status = mech->gss_compare_name(minor_status,
+#endif
+                                         union_name1->mech_name,
+                                         internal_name, name_equal);
+    __gss_release_internal_name(&temp_minor, union_name1->mech_type,
+                               &internal_name);
+    return (major_status);
+
+}
diff --git a/support/gssapi/g_context_time.c b/support/gssapi/g_context_time.c
new file mode 100644 (file)
index 0000000..13ae5c8
--- /dev/null
@@ -0,0 +1,75 @@
+/* #ident  "@(#)gss_context_time.c 1.8     95/08/07 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routines for gss_context_time
+ */
+
+#include "mglueP.h"
+
+OM_uint32 KRB5_CALLCONV
+gss_context_time (minor_status,
+                  context_handle,
+                  time_rec)
+
+OM_uint32 *            minor_status;
+gss_ctx_id_t           context_handle;
+OM_uint32 *            time_rec;
+
+{
+    OM_uint32          status;
+    gss_union_ctx_id_t ctx;
+    gss_mechanism      mech;
+
+    gss_initialize();
+
+    if (context_handle == GSS_C_NO_CONTEXT)
+       return GSS_S_NO_CONTEXT;
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    ctx = (gss_union_ctx_id_t) context_handle;
+    mech = __gss_get_mechanism (ctx->mech_type);
+
+    if (mech) {
+
+       if (mech->gss_context_time)
+           status = mech->gss_context_time(
+#ifdef USE_MECH_CONTEXT
+                                           mech->context,
+#endif
+                                           minor_status,
+                                           ctx->internal_ctx_id,
+                                           time_rec);
+       else
+           status = GSS_S_BAD_BINDINGS;
+
+       return(status);
+    }
+
+    return(GSS_S_NO_CONTEXT);
+}
diff --git a/support/gssapi/g_delete_sec_context.c b/support/gssapi/g_delete_sec_context.c
new file mode 100644 (file)
index 0000000..e9253c8
--- /dev/null
@@ -0,0 +1,88 @@
+/* #ident  "@(#)gss_delete_sec_context.c 1.10     95/08/07 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_delete_sec_context
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+OM_uint32 KRB5_CALLCONV
+gss_delete_sec_context (minor_status,
+                        context_handle,
+                        output_token)
+
+OM_uint32 *            minor_status;
+gss_ctx_id_t *         context_handle;
+gss_buffer_t           output_token;
+
+{
+    OM_uint32          status;
+    gss_union_ctx_id_t ctx;
+    gss_mechanism      mech;
+
+    gss_initialize();
+
+    /* if the context_handle is Null, return NO_CONTEXT error */
+
+    if(context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT)
+       return(GSS_S_NO_CONTEXT);
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    ctx = (gss_union_ctx_id_t) *context_handle;
+    mech = __gss_get_mechanism (ctx->mech_type);
+
+    if (mech) {
+
+       if (mech->gss_delete_sec_context)
+           status = mech->gss_delete_sec_context(
+#ifdef USE_MECH_CONTEXT
+                                                 mech->context,
+#endif
+                                                 minor_status,
+                                                 &ctx->internal_ctx_id,
+                                                 output_token);
+       else
+           status = GSS_S_BAD_BINDINGS;
+
+       /* now free up the space for the union context structure */
+
+       free(ctx->mech_type->elements);
+       free(ctx->mech_type);
+       free(*context_handle);
+       *context_handle = NULL;
+
+       return(status);
+    }
+
+    return(GSS_S_NO_CONTEXT);
+}
diff --git a/support/gssapi/g_dsp_name.c b/support/gssapi/g_dsp_name.c
new file mode 100644 (file)
index 0000000..dcf1800
--- /dev/null
@@ -0,0 +1,96 @@
+/* #ident  "@(#)g_dsp_name.c 1.2     96/02/06 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_display_name()
+ *
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+OM_uint32 KRB5_CALLCONV
+gss_display_name (minor_status,
+                  input_name,
+                  output_name_buffer,
+                  output_name_type)
+
+OM_uint32 *            minor_status;
+gss_name_t             input_name;
+gss_buffer_t           output_name_buffer;
+gss_OID *              output_name_type;
+
+{
+    OM_uint32          major_status;
+    gss_union_name_t   union_name;
+
+    if (input_name == 0)
+       return GSS_S_BAD_NAME;
+
+    union_name = (gss_union_name_t) input_name;
+
+    if (union_name->mech_type) {
+       /*
+        * OK, we have a mechanism-specific name; let's use it!
+        */
+       return (__gss_display_internal_name(minor_status,
+                                           union_name->mech_type,
+                                           union_name->mech_name,
+                                           output_name_buffer,
+                                           output_name_type));
+    }
+
+    /*
+     * copy the value of the external_name component of the union
+     * name into the output_name_buffer and point the output_name_type
+     * to the name_type component of union_name
+     */
+    if (output_name_type != NULL) {
+       major_status = generic_gss_copy_oid(minor_status,
+                                           union_name->name_type,
+                                           output_name_type);
+       if (major_status)
+           return (major_status);
+    }
+
+    if (output_name_buffer != NULL) {
+       output_name_buffer->length = union_name->external_name->length;
+
+       output_name_buffer->value =
+           (void *) malloc(output_name_buffer->length);
+
+       memcpy(output_name_buffer->value,
+              union_name->external_name->value,
+              output_name_buffer->length);
+    }
+
+    if (minor_status)
+       *minor_status = 0;
+
+    return(GSS_S_COMPLETE);
+}
diff --git a/support/gssapi/g_dsp_status.c b/support/gssapi/g_dsp_status.c
new file mode 100644 (file)
index 0000000..42cae0d
--- /dev/null
@@ -0,0 +1,86 @@
+/* #ident  "@(#)gss_display_status.c 1.8     95/08/07 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine gss_display_status
+ *
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+OM_uint32 KRB5_CALLCONV
+gss_display_status (minor_status,
+                    status_value,
+                    status_type,
+                    req_mech_type,
+                    message_context,
+                    status_string)
+
+OM_uint32 *            minor_status;
+OM_uint32              status_value;
+int                    status_type;
+gss_OID                        req_mech_type;
+OM_uint32 *            message_context;
+gss_buffer_t           status_string;
+
+{
+    OM_uint32          status;
+    gss_OID            mech_type = (gss_OID) req_mech_type;
+    gss_mechanism      mech;
+
+    gss_initialize();
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    mech = __gss_get_mechanism (mech_type);
+
+    if (mech == NULL)
+       return (GSS_S_BAD_MECH);
+
+    if (mech_type == GSS_C_NULL_OID)
+       mech_type = &mech->mech_type;
+
+    if (mech->gss_display_status)
+       status = mech->gss_display_status(
+#ifdef USE_MECH_CONTEXT
+                                         mech->context,
+#endif
+                                         minor_status,
+                                         status_value,
+                                         status_type,
+                                         mech_type,
+                                         message_context,
+                                         status_string);
+    else
+       status = GSS_S_BAD_BINDINGS;
+
+    return(status);
+}
diff --git a/support/gssapi/g_dup_name.c b/support/gssapi/g_dup_name.c
new file mode 100644 (file)
index 0000000..bb88813
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+                                * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * created andros 2.24.01 from g_compare_name.c
+ */
+
+/*
+ *  glue routine for gss_duplicate_name
+ *
+ */
+
+#include <stdio.h>
+#include "mglueP.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+OM_uint32 KRB5_CALLCONV
+gss_duplicate_name (minor_status,
+                   in_name,
+                   exp_name)
+OM_uint32 *            minor_status;
+const gss_name_t               in_name;
+gss_name_t             *exp_name;
+{
+    OM_uint32          tmp,major_status =  GSS_S_COMPLETE;
+    gss_union_name_t   union_in_name, union_exp_name;
+    gss_mechanism      mech;
+
+    gss_initialize();
+
+    /* if exp_name is NULL, simply return */
+    if (exp_name == NULL)
+       return (GSS_S_COMPLETE);
+
+    *exp_name = NULL;
+
+    if (in_name == 0)
+       return (GSS_S_BAD_NAME);
+
+    union_in_name = (gss_union_name_t) in_name;
+
+    /*
+     * Create the union name struct that will hold the exported
+     * name and the name type.
+     */
+
+    union_exp_name = (gss_union_name_t) malloc (sizeof(gss_union_name_desc));
+    if (!union_exp_name) {
+       *minor_status = ENOMEM;
+       goto allocation_failure;
+    }
+#ifdef DEBUG
+    fprintf(stderr, "gss_duplicate_name: copying *oid %p\n",
+               union_in_name->mech_type);
+#endif
+    union_exp_name->gss_mech = union_in_name->gss_mech;
+    union_exp_name->mech_type = GSS_C_NO_OID;
+    if (union_in_name->mech_type != GSS_C_NO_OID &&
+       (generic_gss_copy_oid(&tmp, union_in_name->mech_type,
+                       &union_exp_name->mech_type) != GSS_S_COMPLETE)) {
+       *minor_status = ENOMEM;
+       goto allocation_failure;
+    }
+    union_exp_name->mech_name = NULL;
+    union_exp_name->name_type = GSS_C_NO_OID;
+    if (union_in_name->name_type != GSS_C_NO_OID &&
+       (generic_gss_copy_oid(&tmp, union_in_name->name_type,
+                       &union_exp_name->name_type) != GSS_S_COMPLETE)) {
+       *minor_status = ENOMEM;
+       goto allocation_failure;
+    }
+    union_exp_name->external_name = NULL;
+    union_exp_name->external_name =
+                       (gss_buffer_t) malloc(sizeof(gss_buffer_desc));
+    if (!union_exp_name->external_name) {
+       *minor_status = ENOMEM;
+       goto allocation_failure;
+    }
+    union_exp_name->external_name->length = union_in_name->external_name->length;
+    /*
+     * we malloc length+1 to stick a NULL on the end, just in case
+     * Note that this NULL is not included in ->length for a reason!
+     */
+
+    union_exp_name->external_name->value =
+    (void  *) malloc(union_in_name->external_name->length);
+    if (!union_exp_name->external_name->value) {
+       *minor_status = ENOMEM;
+       goto allocation_failure;
+    }
+    memcpy(union_exp_name->external_name->value,
+       union_in_name->external_name->value,
+       union_exp_name->external_name->length);
+
+    /*
+     * Mechanism specific name
+     */
+
+    if (union_in_name->mech_type != GSS_C_NO_OID) {
+       mech = __gss_get_mechanism (union_in_name->mech_type);
+       if (!mech)
+           return (GSS_S_BAD_MECH);
+       if (!mech->gss_duplicate_name)
+           return (GSS_S_BAD_BINDINGS);
+
+#ifdef USE_MECH_CONTEXT
+       major_status = mech->gss_duplicate_name(mech->context, minor_status,
+#else
+       major_status = mech->gss_duplicate_name(minor_status,
+#endif
+           union_in_name->mech_name, &union_exp_name->mech_name);
+       if (major_status != GSS_S_COMPLETE)
+           return (major_status);
+    }
+#ifdef DEBUG
+    fprintf(stderr, "gss_duplicate_name: returning union_exp_name %p\n",
+               union_exp_name);
+#endif
+    *exp_name = union_exp_name;
+    return (major_status);
+
+allocation_failure:
+    if (union_exp_name) {
+       if (union_exp_name->external_name) {
+           if (union_exp_name->external_name->value)
+               free(union_exp_name->external_name->value);
+               free(union_exp_name->external_name);
+       }
+       if (union_exp_name->name_type)
+           generic_gss_release_oid(&tmp, &union_exp_name->name_type);
+       if (union_exp_name->mech_name)
+           __gss_release_internal_name(minor_status, union_exp_name->mech_type,
+               &union_exp_name->mech_name);
+       if (union_exp_name->mech_type)
+           generic_gss_release_oid(&tmp, &union_exp_name->mech_type);
+           free(union_exp_name);
+    }
+return (major_status);
+
+}
+
diff --git a/support/gssapi/g_exp_sec_context.c b/support/gssapi/g_exp_sec_context.c
new file mode 100644 (file)
index 0000000..59d9e80
--- /dev/null
@@ -0,0 +1,108 @@
+/* #ident  "@(#)g_exp_sec_context.c 1.2     96/01/18 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_export_sec_context
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+OM_uint32 KRB5_CALLCONV
+gss_export_sec_context(minor_status,
+                       context_handle,
+                       interprocess_token)
+
+OM_uint32 *            minor_status;
+gss_ctx_id_t *         context_handle;
+gss_buffer_t           interprocess_token;
+
+{
+    OM_uint32          status;
+    size_t             length;
+    gss_union_ctx_id_t ctx;
+    gss_mechanism      mech;
+    gss_buffer_desc    token;
+    char               *buf;
+
+    gss_initialize();
+
+    if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT)
+       return GSS_S_NO_CONTEXT;
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    ctx = (gss_union_ctx_id_t) *context_handle;
+    mech = __gss_get_mechanism (ctx->mech_type);
+    if (!mech)
+       return GSS_S_BAD_MECH;
+    if (!mech->gss_export_sec_context)
+       return GSS_S_BAD_BINDINGS;
+
+#ifdef USE_MECH_CONTEXT
+    status = mech->gss_export_sec_context(mech->context, minor_status,
+#else
+    status = mech->gss_export_sec_context(minor_status,
+#endif
+                                         &ctx->internal_ctx_id, &token);
+    if (status != GSS_S_COMPLETE)
+       return (status);
+
+    length = token.length + 4 + ctx->mech_type->length;
+    interprocess_token->length = length;
+    interprocess_token->value = malloc(length);
+    if (interprocess_token->value == 0) {
+       (void) gss_release_buffer(minor_status, &token);
+       *minor_status = ENOMEM;
+       return (GSS_S_FAILURE);
+    }
+    buf = interprocess_token->value;
+    length = ctx->mech_type->length;
+    buf[3] = (unsigned char) (length & 0xFF);
+    length >>= 8;
+    buf[2] = (unsigned char) (length & 0xFF);
+    length >>= 8;
+    buf[1] = (unsigned char) (length & 0xFF);
+    length >>= 8;
+    buf[0] = (unsigned char) (length & 0xFF);
+    memcpy(buf+4, ctx->mech_type->elements, (size_t) ctx->mech_type->length);
+    memcpy(buf+4+ctx->mech_type->length, token.value, token.length);
+
+    (void) gss_release_buffer(minor_status, &token);
+
+    free(ctx->mech_type->elements);
+    free(ctx->mech_type);
+    free(ctx);
+    *context_handle = 0;
+
+    return(GSS_S_COMPLETE);
+}
diff --git a/support/gssapi/g_glue.c b/support/gssapi/g_glue.c
new file mode 100644 (file)
index 0000000..cf2f76a
--- /dev/null
@@ -0,0 +1,344 @@
+/* #ident      "@(#)g_glue.c 1.1     96/02/06 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+#define g_OID_equal(o1,o2) \
+   (((o1)->length == (o2)->length) && \
+    (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0))
+
+extern gss_mechanism *__gss_mechs_array;
+
+/*
+ * This file contains the support routines for the glue layer.
+ */
+
+/*
+ *  given the mechs_array and a mechanism OID, return the
+ *  pointer to the mechanism, or NULL if that mechanism is
+ *  not supported.  If the requested OID is NULL, then return
+ *  the first mechanism.
+ */
+
+gss_mechanism __gss_get_mechanism (type)
+     gss_OID type;
+{
+    int        i;
+
+    if (type == GSS_C_NULL_OID)
+       return (__gss_mechs_array[0]);
+
+    for (i=0; __gss_mechs_array[i]->mech_type.length != 0; i++) {
+       if ((__gss_mechs_array[i]->mech_type.length == type->length) &&
+           (memcmp (__gss_mechs_array[i]->mech_type.elements, type->elements,
+                    type->length) == 0)) {
+
+           return (__gss_mechs_array[i]);
+       }
+    }
+    return NULL;
+}
+
+
+/*
+ *  glue routine for get_mech_type
+ *
+ */
+
+OM_uint32 __gss_get_mech_type(OID, token)
+    gss_OID            OID;
+    gss_buffer_t       token;
+{
+    unsigned char * buffer_ptr;
+    int length;
+
+    /*
+     * This routine reads the prefix of "token" in order to determine
+     * its mechanism type. It assumes the encoding suggested in
+     * Appendix B of RFC 1508. This format starts out as follows :
+     *
+     * tag for APPLICATION 0, Sequence[constructed, definite length]
+     * length of remainder of token
+     * tag of OBJECT IDENTIFIER
+     * length of mechanism OID
+     * encoding of mechanism OID
+     * <the rest of the token>
+     *
+     * Numerically, this looks like :
+     *
+     * 0x60
+     * <length> - could be multiple bytes
+     * 0x06
+     * <length> - assume only one byte, hence OID length < 127
+     * <mech OID bytes>
+     *
+     * The routine fills in the OID value and returns an error as necessary.
+     */
+
+    if (token == NULL)
+       return (GSS_S_DEFECTIVE_TOKEN);
+
+    /* Skip past the APP/Sequnce byte and the token length */
+
+    buffer_ptr = (unsigned char *) token->value;
+
+    if (*(buffer_ptr++) != 0x60)
+       return (GSS_S_DEFECTIVE_TOKEN);
+    length = *buffer_ptr++;
+    if (length & 0x80) {
+       if ((length & 0x7f) > 4)
+           return (GSS_S_DEFECTIVE_TOKEN);
+       buffer_ptr += length & 0x7f;
+    }
+
+    if (*(buffer_ptr++) != 0x06)
+       return (GSS_S_DEFECTIVE_TOKEN);
+
+    OID->length = (OM_uint32) *(buffer_ptr++);
+    OID->elements = (void *) buffer_ptr;
+    return (GSS_S_COMPLETE);
+}
+
+
+/*
+ *  Internal routines to get and release an internal mechanism name
+ */
+
+#include "mglueP.h"
+
+OM_uint32 __gss_import_internal_name (minor_status, mech_type, union_name,
+                               internal_name)
+OM_uint32      *minor_status;
+gss_OID                mech_type;
+gss_union_name_t       union_name;
+gss_name_t     *internal_name;
+{
+    OM_uint32          status;
+    gss_mechanism      mech;
+
+    mech = __gss_get_mechanism (mech_type);
+    if (mech) {
+       if (mech->gss_import_name)
+           status = mech->gss_import_name (
+#ifdef USE_MECH_CONTEXT
+                                           mech->context,
+#endif
+                                           minor_status,
+                                           union_name->external_name,
+                                           union_name->name_type,
+                                           internal_name);
+       else
+           status = GSS_S_BAD_BINDINGS;
+
+       return (status);
+    }
+
+    return (GSS_S_BAD_MECH);
+}
+
+OM_uint32 __gss_display_internal_name (minor_status, mech_type, internal_name,
+                                external_name, name_type)
+OM_uint32      *minor_status;
+gss_OID                mech_type;
+gss_name_t     internal_name;
+gss_buffer_t   external_name;
+gss_OID                *name_type;
+{
+    OM_uint32          status;
+    gss_mechanism      mech;
+
+    mech = __gss_get_mechanism (mech_type);
+    if (mech) {
+       if (mech->gss_display_name)
+           status = mech->gss_display_name (
+#ifdef USE_MECH_CONTEXT
+                                            mech->context,
+#endif
+                                            minor_status,
+                                            internal_name,
+                                            external_name,
+                                            name_type);
+       else
+           status = GSS_S_BAD_BINDINGS;
+
+       return (status);
+    }
+
+    return (GSS_S_BAD_MECH);
+}
+
+OM_uint32 __gss_release_internal_name (minor_status, mech_type, internal_name)
+OM_uint32      *minor_status;
+gss_OID                mech_type;
+gss_name_t     *internal_name;
+{
+    OM_uint32          status;
+    gss_mechanism      mech;
+
+    mech = __gss_get_mechanism (mech_type);
+    if (mech) {
+       if (mech->gss_release_name)
+           status = mech->gss_release_name (
+#ifdef USE_MECH_CONTEXT
+                                            mech->context,
+#endif
+                                            minor_status,
+                                            internal_name);
+       else
+           status = GSS_S_BAD_BINDINGS;
+
+       return (status);
+    }
+
+    return (GSS_S_BAD_MECH);
+}
+
+
+/*
+ * This function converts an internal gssapi name to a union gssapi
+ * name.  Note that internal_name should be considered "consumed" by
+ * this call, whether or not we return an error.
+ */
+OM_uint32 __gss_convert_name_to_union_name(minor_status, mech,
+                                          internal_name, external_name)
+    OM_uint32 *minor_status;
+    gss_mechanism      mech;
+    gss_name_t internal_name;
+    gss_name_t *external_name;
+{
+    OM_uint32 major_status,tmp;
+    gss_union_name_t union_name;
+
+    union_name = (gss_union_name_t) malloc (sizeof(gss_union_name_desc));
+    if (!union_name) {
+           *minor_status = ENOMEM;
+           goto allocation_failure;
+    }
+    union_name->mech_type = 0;
+    union_name->mech_name = internal_name;
+    union_name->name_type = 0;
+    union_name->external_name = 0;
+    union_name->gss_mech = mech;
+
+    major_status = generic_gss_copy_oid(minor_status, &mech->mech_type,
+                                       &union_name->mech_type);
+    if (major_status != GSS_S_COMPLETE)
+       goto allocation_failure;
+
+    union_name->external_name =
+       (gss_buffer_t) malloc(sizeof(gss_buffer_desc));
+    if (!union_name->external_name) {
+           *minor_status = ENOMEM;
+           goto allocation_failure;
+    }
+
+#ifdef USE_MECH_CONTEXT
+    major_status = mech->gss_display_name(mech->context, minor_status,
+#else
+    major_status = mech->gss_display_name(minor_status,
+#endif
+                                         internal_name,
+                                         union_name->external_name,
+                                         &union_name->name_type);
+    if (major_status != GSS_S_COMPLETE)
+       goto allocation_failure;
+
+    *external_name =  union_name;
+    return (GSS_S_COMPLETE);
+
+allocation_failure:
+    if (union_name) {
+       if (union_name->external_name) {
+           if (union_name->external_name->value)
+               free(union_name->external_name->value);
+           free(union_name->external_name);
+       }
+       if (union_name->name_type)
+           generic_gss_release_oid(&tmp, &union_name->name_type);
+       if (union_name->mech_name)
+           __gss_release_internal_name(minor_status, union_name->mech_type,
+                                       &union_name->mech_name);
+       if (union_name->mech_type)
+           mech_gss_release_oid(&tmp, &union_name->mech_type, mech);
+       free(union_name);
+    }
+    return (major_status);
+}
+
+/*
+ * Glue routine for returning the mechanism-specific credential from a
+ * external union credential.
+ */
+gss_cred_id_t
+__gss_get_mechanism_cred(union_cred, mech_type)
+    gss_union_cred_t   union_cred;
+    gss_OID            mech_type;
+{
+    int                i;
+
+    if (union_cred == GSS_C_NO_CREDENTIAL)
+       return GSS_C_NO_CREDENTIAL;
+
+    for (i=0; i < union_cred->count; i++) {
+       if (g_OID_equal(mech_type, &union_cred->mechs_array[i]))
+           return union_cred->cred_array[i];
+    }
+    return GSS_C_NO_CREDENTIAL;
+}
+
+
+/*
+ * Glue routine to copy an external name buffer (used by gss_duplicate_name)
+ */
+OM_uint32 __gss_copy_namebuf(src, dest)
+    gss_buffer_t   src;
+    gss_buffer_t   *dest;
+{
+    gss_buffer_t   temp = NULL;
+
+    if (dest == NULL)
+       return (GSS_S_BAD_NAME);
+
+    temp = (gss_buffer_t) malloc (sizeof(gss_buffer_t));
+    if (!temp) {
+       return(GSS_S_FAILURE);
+    }
+    temp->value = (void *) malloc (src->length + 1);
+    if (temp->value == NULL) {
+        free(temp);
+       return(GSS_S_FAILURE);
+    }
+
+    memcpy(temp->value, src->value, src->length);
+    temp->length = src->length;
+
+    *dest = temp;
+    return (GSS_S_COMPLETE);
+}
diff --git a/support/gssapi/g_imp_name.c b/support/gssapi/g_imp_name.c
new file mode 100644 (file)
index 0000000..43f9c50
--- /dev/null
@@ -0,0 +1,161 @@
+/* #ident  "@(#)g_imp_name.c 1.2     96/02/06 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine gss_import_name
+ *
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+OM_uint32 KRB5_CALLCONV
+gss_import_name(minor_status,
+                input_name_buffer,
+                input_name_type,
+                output_name)
+
+OM_uint32 *            minor_status;
+gss_buffer_t           input_name_buffer;
+gss_OID                        input_name_type;
+gss_name_t *           output_name;
+
+{
+    gss_union_name_t   union_name;
+    OM_uint32          tmp, major_status = GSS_S_FAILURE;
+    gss_OID            mech;
+
+    gss_initialize();
+
+    if (minor_status)
+       *minor_status = 0;
+
+    /* if output_name is NULL, simply return */
+
+    if(output_name == NULL)
+       return (GSS_S_COMPLETE);
+
+    *output_name = 0;
+
+    if (input_name_buffer == GSS_C_NO_BUFFER)
+       return (GSS_S_BAD_NAME);
+
+    /*
+     * First create the union name struct that will hold the external
+     * name and the name type.
+     */
+
+    union_name = (gss_union_name_t) malloc (sizeof(gss_union_name_desc));
+    if (!union_name) {
+           *minor_status = ENOMEM;
+           goto allocation_failure;
+    }
+    union_name->mech_type = 0;
+    union_name->mech_name = 0;
+    union_name->name_type = 0;
+    union_name->external_name = 0;
+    union_name->gss_mech = NULL;
+
+    /*
+     * All we do here is record the external name and name_type.
+     * When the name is actually used, the underlying gss_import_name()
+     * is called for the appropriate mechanism. Note that the name type
+     * is assumed to be constant, so only a pointer to it is stored in
+     * union_name
+     */
+    union_name->external_name =
+       (gss_buffer_t) malloc(sizeof(gss_buffer_desc));
+    if (!union_name->external_name) {
+           *minor_status = ENOMEM;
+           goto allocation_failure;
+    }
+
+    union_name->external_name->length = input_name_buffer->length;
+    /* we malloc length+1 to stick a NULL on the end, just in case */
+    /* Note that this NULL is not included in ->length for a reason! */
+    union_name->external_name->value =
+       (void  *) malloc(input_name_buffer->length+1);
+    if (!union_name->external_name->value) {
+       *minor_status = ENOMEM;
+       goto allocation_failure;
+    }
+
+    memcpy(union_name->external_name->value, input_name_buffer->value,
+          input_name_buffer->length);
+
+    /* add NULL to end of external_name->value, just in case... */
+    ((char *)union_name->external_name->value)
+                               [input_name_buffer->length] = '\0';
+
+    major_status = generic_gss_copy_oid(minor_status, input_name_type,
+                                       &union_name->name_type);
+    if (major_status != GSS_S_COMPLETE)
+       goto allocation_failure;
+
+    /*
+     * See if this is a mechanism-specific name.  If so, let's import
+     * it now so we can get any error messages, and to avoid trouble
+     * later...
+     */
+    mech = gss_find_mechanism_from_name_type(input_name_type);
+    if (mech) {
+       major_status = generic_gss_copy_oid(minor_status, mech,
+                                           &union_name->mech_type);
+       if (major_status != GSS_S_COMPLETE)
+           goto allocation_failure;
+
+       major_status = __gss_import_internal_name(minor_status, mech,
+                                                 union_name,
+                                                 &union_name->mech_name);
+       if (major_status)
+           goto allocation_failure;
+    }
+
+    *output_name = (gss_name_t) union_name;
+
+    return(GSS_S_COMPLETE);
+
+allocation_failure:
+    if (union_name) {
+       if (union_name->external_name) {
+           if (union_name->external_name->value)
+               free(union_name->external_name->value);
+           free(union_name->external_name);
+       }
+       if (union_name->name_type)
+           generic_gss_release_oid(&tmp, &union_name->name_type);
+       if (union_name->mech_name)
+           __gss_release_internal_name(minor_status, union_name->mech_type,
+                                       &union_name->mech_name);
+       if (union_name->mech_type)
+           generic_gss_release_oid(&tmp, &union_name->mech_type);
+       free(union_name);
+    }
+    return (major_status);
+}
diff --git a/support/gssapi/g_imp_sec_context.c b/support/gssapi/g_imp_sec_context.c
new file mode 100644 (file)
index 0000000..faa58ed
--- /dev/null
@@ -0,0 +1,128 @@
+/* #ident  "@(#)g_imp_sec_context.c 1.2     96/01/18 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine gss_export_sec_context
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+OM_uint32 KRB5_CALLCONV
+gss_import_sec_context(minor_status,
+                       interprocess_token,
+                       context_handle)
+
+OM_uint32 *            minor_status;
+gss_buffer_t           interprocess_token;
+gss_ctx_id_t *         context_handle;
+
+{
+    size_t             length;
+    OM_uint32          status;
+    char               *p;
+    gss_union_ctx_id_t ctx;
+    gss_buffer_desc    token;
+    gss_mechanism      mech;
+
+    gss_initialize();
+
+    *minor_status = 0;
+
+    if (interprocess_token->length == 0 || interprocess_token->value == 0)
+       return (GSS_S_DEFECTIVE_TOKEN);
+
+    status = GSS_S_FAILURE;
+
+    ctx = (gss_union_ctx_id_t) malloc(sizeof(gss_union_ctx_id_desc));
+    if (!ctx) {
+       *minor_status = ENOMEM;
+       goto error_out;
+    }
+    ctx->mech_type = (gss_OID) malloc(sizeof(gss_OID_desc));
+    if (!ctx->mech_type) {
+       *minor_status = ENOMEM;
+       goto error_out;
+    }
+    p = interprocess_token->value;
+    length = *p++;
+    length = (length << 8) + *p++;
+    length = (length << 8) + *p++;
+    length = (length << 8) + *p++;
+
+    ctx->mech_type->length = length;
+    ctx->mech_type->elements = malloc(length);
+    if (!ctx->mech_type->elements) {
+       *minor_status = ENOMEM;
+       goto error_out;
+    }
+    memcpy(ctx->mech_type->elements, p, length);
+    p += length;
+
+    token.length = interprocess_token->length - 4 - length;
+    token.value = p;
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    mech = __gss_get_mechanism (ctx->mech_type);
+    if (!mech) {
+       status = GSS_S_BAD_MECH;
+       goto error_out;
+    }
+    if (!mech->gss_import_sec_context) {
+       status = GSS_S_BAD_BINDINGS;
+       goto error_out;
+    }
+
+#ifdef USE_MECH_CONTEXT
+    status = mech->gss_import_sec_context(mech->context, minor_status,
+#else
+    status = mech->gss_import_sec_context(minor_status,
+#endif
+                                         &token, &ctx->internal_ctx_id);
+
+    if (status == GSS_S_COMPLETE) {
+       *context_handle = ctx;
+       return (GSS_S_COMPLETE);
+    }
+
+error_out:
+    if (ctx) {
+       if (ctx->mech_type) {
+           if (ctx->mech_type->elements)
+               free(ctx->mech_type->elements);
+           free(ctx->mech_type);
+       }
+       free(ctx);
+    }
+    return status;
+}
diff --git a/support/gssapi/g_indicate_mechs.c b/support/gssapi/g_indicate_mechs.c
new file mode 100644 (file)
index 0000000..9006d6d
--- /dev/null
@@ -0,0 +1,90 @@
+/* #ident  "@(#)gss_indicate_mechs.c 1.13     95/08/04 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_indicate_mechs
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+extern gss_mechanism *__gss_mechs_array;
+
+static gss_OID_set_desc        supported_mechs_desc;
+static gss_OID_set supported_mechs = NULL;
+
+OM_uint32 KRB5_CALLCONV
+gss_indicate_mechs (minor_status,
+                    mech_set)
+
+OM_uint32 *            minor_status;
+gss_OID_set *          mech_set;
+
+{
+    int i;
+
+    gss_initialize();
+
+    if (minor_status)
+       *minor_status = 0;
+
+    /*
+     * If we have already computed the mechanisms supported, return
+     * a pointer to it. Otherwise, compute them and return the pointer.
+     */
+
+    if(supported_mechs == NULL) {
+
+       supported_mechs = &supported_mechs_desc;
+       supported_mechs->count = 0;
+
+       /* Build the mech_set from the OIDs in mechs_array. */
+
+       for(i=0; __gss_mechs_array[i]->mech_type.length != 0; i++)
+           supported_mechs->count++;
+
+       supported_mechs->elements =
+           (void *) malloc(supported_mechs->count *
+                           sizeof(gss_OID_desc));
+
+       for(i=0; i < supported_mechs->count; i++) {
+           supported_mechs->elements[i].length =
+               __gss_mechs_array[i]->mech_type.length;
+           supported_mechs->elements[i].elements = (void *)
+               malloc(__gss_mechs_array[i]->mech_type.length);
+           memcpy(supported_mechs->elements[i].elements,
+                  __gss_mechs_array[i]->mech_type.elements,
+                  __gss_mechs_array[i]->mech_type.length);
+       }
+    }
+
+    if(mech_set != NULL)
+       *mech_set = supported_mechs;
+
+    return(GSS_S_COMPLETE);
+}
diff --git a/support/gssapi/g_init_sec_context.c b/support/gssapi/g_init_sec_context.c
new file mode 100644 (file)
index 0000000..a838597
--- /dev/null
@@ -0,0 +1,194 @@
+/* #ident  "@(#)gss_init_sec_context.c 1.20     95/08/07 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_init_sec_context
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+#define g_OID_equal(o1,o2) \
+   (((o1)->length == (o2)->length) && \
+    (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0))
+
+OM_uint32 KRB5_CALLCONV
+gss_init_sec_context (minor_status,
+                      claimant_cred_handle,
+                      context_handle,
+                      target_name,
+                      req_mech_type,
+                      req_flags,
+                      time_req,
+                      input_chan_bindings,
+                      input_token,
+                      actual_mech_type,
+                      output_token,
+                      ret_flags,
+                      time_rec)
+
+OM_uint32 *            minor_status;
+gss_cred_id_t          claimant_cred_handle;
+gss_ctx_id_t *         context_handle;
+gss_name_t             target_name;
+gss_OID                        req_mech_type;
+OM_uint32              req_flags;
+OM_uint32              time_req;
+gss_channel_bindings_t input_chan_bindings;
+gss_buffer_t           input_token;
+gss_OID *              actual_mech_type;
+gss_buffer_t           output_token;
+OM_uint32 *            ret_flags;
+OM_uint32 *            time_rec;
+
+{
+    OM_uint32          status, temp_status, temp_minor_status;
+    gss_union_name_t   union_name;
+    gss_union_cred_t   union_cred;
+    gss_name_t         internal_name;
+    gss_union_ctx_id_t union_ctx_id;
+    gss_OID            mech_type = (gss_OID) req_mech_type;
+    gss_mechanism      mech;
+    gss_cred_id_t      input_cred_handle;
+
+    gss_initialize();
+
+    if (context_handle == NULL)
+       return GSS_S_NO_CONTEXT;
+
+    union_name = (gss_union_name_t) target_name;
+
+    /*
+     * If mech_type is NULL, and the target_name is
+     * mechanism-specific, then set it to the mech_type of
+     * target_name.
+     */
+    if ((mech_type == GSS_C_NULL_OID) && union_name->mech_type)
+       mech_type = union_name->mech_type;
+
+    /*
+     * obtain the gss mechanism information for the requested
+     * mechanism.  If mech_type is NULL, set it to the resultant
+     * mechanism
+     */
+    mech = __gss_get_mechanism (mech_type);
+    if (mech == NULL)
+       return (GSS_S_BAD_MECH);
+
+    if (mech_type == GSS_C_NULL_OID)
+       mech_type = &mech->mech_type;
+
+    /*
+     * If target_name is mechanism_specific, then it must match the
+     * mech_type that we're about to use.  Otherwise, do an import on
+     * the external_name form of the target name.
+     */
+    if (union_name->mech_type) {
+       if (!g_OID_equal(union_name->mech_type, mech_type))
+           return (GSS_S_BAD_MECH);
+       internal_name = union_name->mech_name;
+    } else {
+       if ((temp_status = __gss_import_internal_name(minor_status, mech_type,
+                                                     union_name,
+                                                     &internal_name)))
+           return (GSS_S_BAD_NAME);
+    }
+
+    /*
+     * if context_handle is GSS_C_NO_CONTEXT, allocate a union context
+     * descriptor to hold the mech type information as well as the
+     * underlying mechanism context handle. Otherwise, cast the
+     * value of *context_handle to the union context variable.
+     */
+
+    if(*context_handle == GSS_C_NO_CONTEXT) {
+       union_ctx_id = (gss_union_ctx_id_t)
+           malloc(sizeof(gss_union_ctx_id_desc));
+
+       union_ctx_id->mech_type = (gss_OID)
+           malloc(sizeof(gss_OID_desc));
+
+       /* copy in the mech type information */
+
+       union_ctx_id->mech_type->elements = (void *)
+           malloc(mech_type->length);
+
+       union_ctx_id->mech_type->length = mech_type->length;
+       memcpy(union_ctx_id->mech_type->elements, mech_type->elements,
+              mech_type->length);
+
+       /* copy the supplied context handle */
+
+       union_ctx_id->internal_ctx_id = *context_handle;
+    } else
+       union_ctx_id = *context_handle;
+
+    /*
+     * get the appropriate cred handle from the union cred struct.
+     * defaults to GSS_C_NO_CREDENTIAL if there is no cred, which will
+     * use the default credential.
+     */
+    union_cred = (gss_union_cred_t) claimant_cred_handle;
+    input_cred_handle = __gss_get_mechanism_cred(union_cred, mech_type);
+
+    /*
+     * now call the approprate underlying mechanism routine
+     */
+
+    if (mech->gss_init_sec_context) {
+       status = mech->gss_init_sec_context(
+#ifdef USE_MECH_CONTEXT
+                                           mech->context,
+#endif
+                                           minor_status,
+                                           input_cred_handle,
+                                           &union_ctx_id->internal_ctx_id,
+                                           internal_name,
+                                           mech_type,
+                                           req_flags,
+                                           time_req,
+                                           input_chan_bindings,
+                                           input_token,
+                                           actual_mech_type,
+                                           output_token,
+                                           ret_flags,
+                                           time_rec);
+
+       if (*context_handle == GSS_C_NO_CONTEXT)
+           *context_handle = (gss_ctx_id_t) union_ctx_id;
+
+    } else
+       status = GSS_S_BAD_BINDINGS;
+
+    if (!union_name->mech_type) {
+       (void) __gss_release_internal_name(&temp_minor_status,
+                                          mech_type, &internal_name);
+    }
+
+    return(status);
+}
diff --git a/support/gssapi/g_initialize.c b/support/gssapi/g_initialize.c
new file mode 100644 (file)
index 0000000..9523d40
--- /dev/null
@@ -0,0 +1,380 @@
+/* #ident  "@(#)g_initialize.c 1.2     96/02/06 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This function will initialize the gssapi mechglue library
+ */
+
+#include "config.h"
+#include "mglueP.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#ifdef USE_SOLARIS_SHARED_LIBRARIES
+#include <dlfcn.h>
+
+#define MECH_CONF "/etc/mech.conf"
+#define MECH_SYM "gss_mech_initialize"
+
+static void solaris_initialize (void);
+#endif /* USE_SOLARIS_SHARED_LIBRARIES */
+
+#ifdef __linux__
+#define USE_LINUX_SHARED_LIBRARIES
+#endif
+
+#ifdef USE_LINUX_SHARED_LIBRARIES
+#include <dlfcn.h>
+#define MECH_CONF "/etc/gssapi_mech.conf"
+#define MECH_SYM "gss_mech_initialize"
+static void linux_initialize (void);
+#endif /* USE_LINUX_SHARED_LIBRARIES */
+
+#define g_OID_equal(o1,o2) \
+   (((o1)->length == (o2)->length) && \
+    (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0))
+
+extern gss_mechanism krb5_gss_initialize();
+
+static int _gss_initialized = 0;
+
+static struct gss_config null_mech = {
+  {0,NULL}};
+
+gss_mechanism *__gss_mechs_array = NULL;
+
+/*
+ * This function will add a new mechanism to the mechs_array
+ */
+
+static OM_uint32
+add_mechanism (mech, replace)
+     gss_mechanism mech;
+     int replace;
+{
+    gss_mechanism *    temp_array;
+    gss_OID_set                mech_names;
+    OM_uint32          minor_status, major_status;
+    unsigned int       i;
+
+    if (mech == NULL)
+       return GSS_S_COMPLETE;
+
+    /* initialize the mechs_array if it hasn't already been initialized */
+    if (__gss_mechs_array == NULL) {
+       __gss_mechs_array = (gss_mechanism *) malloc (sizeof(gss_mechanism));
+
+       if (__gss_mechs_array == NULL)
+           return ENOMEM;
+
+       __gss_mechs_array[0] = &null_mech;
+    }
+
+    /*
+     * Find the length of __gss_mechs_array, and look for an existing
+     * entry for this OID
+     */
+    for (i=0; __gss_mechs_array[i]->mech_type.length != 0; i++) {
+       if (!g_OID_equal(&__gss_mechs_array[i]->mech_type,
+                        &mech->mech_type))
+           continue;
+
+       /* We found a match.  Replace it? */
+       if (!replace)
+           return GSS_S_FAILURE;
+
+       __gss_mechs_array[i] = mech;
+       return GSS_S_COMPLETE;
+    }
+
+    /* we didn't find it -- add it to the end of the __gss_mechs_array */
+    temp_array = (gss_mechanism *) realloc(__gss_mechs_array,
+                                          (i+2)*sizeof(gss_mechanism));
+
+    if (temp_array == NULL)
+       return ENOMEM;
+
+    temp_array[i++] = mech;
+    temp_array[i] = &null_mech;
+
+    __gss_mechs_array = temp_array;
+
+    /*
+     * OK, now let's register all of the name types this mechanism
+     * knows how to deal with.
+     */
+    major_status = gss_inquire_names_for_mech(&minor_status, &mech->mech_type,
+                                             &mech_names);
+    if (major_status != GSS_S_COMPLETE)
+       return (GSS_S_COMPLETE);
+    for (i=0; i < mech_names->count; i++) {
+       gss_add_mech_name_type(&minor_status, &mech_names->elements[i],
+                              &mech->mech_type);
+    }
+    (void) gss_release_oid_set(&minor_status, &mech_names);
+
+    return GSS_S_COMPLETE;
+}
+
+void gss_initialize ()
+{
+    /* Make sure we've not run already */
+    if (_gss_initialized)
+       return;
+    _gss_initialized = 1;
+
+#ifdef USE_SOLARIS_SHARED_LIBRARIES
+    solaris_initialize();
+
+#elif defined(USE_LINUX_SHARED_LIBRARIES)
+    linux_initialize();
+
+#else
+    {
+       gss_mechanism mech;
+
+       /*
+        * Use hard-coded in mechanisms...  I need to know what mechanisms
+        * are supported...  As more mechanisms become supported, they
+        * should be added here, unless shared libraries are used.
+        */
+
+       /* Initialize the krb5 mechanism */
+       mech = (gss_mechanism)krb5_gss_initialize();
+       if (mech)
+           add_mechanism (mech, 1);
+    }
+
+#endif /* USE_SOLARIS_SHARED_LIBRARIES */
+
+#if !defined(macintosh)
+    if (__gss_mechs_array == NULL) { /* this is very bad! */
+      fprintf(stderr,"gss_initialize fatal error: no mechanisms loaded!\n");
+      exit(-1);
+    }
+#else
+    /*
+     * Nothing for now, since this should never happen using static
+     * mechanism loading.
+     */
+#endif
+
+    return;
+}
+
+#ifdef USE_SOLARIS_SHARED_LIBRARIES
+/*
+ * read the configuration file to find out what mechanisms to
+ * load, load them, and then load the mechanism defitions in
+ * and add the mechanisms
+ */
+static void solaris_initialize ()
+{
+    char buffer[BUFSIZ], *filename, *symname, *endp;
+    FILE *conffile;
+    void *dl;
+    gss_mechanism (*sym)(void), mech;
+
+    if ((filename = getenv("GSSAPI_MECH_CONF")) == NULL)
+       filename = MECH_CONF;
+
+    if ((conffile = fopen(filename, "r")) == NULL) {
+               fprintf(stderr,"fatal error: unable to open %s:"
+                       " errno %d (%s)\n", filename, errno, strerror(errno));
+               return;
+    }
+
+    while (fgets (buffer, BUFSIZ, conffile) != NULL) {
+       /* ignore lines beginning with # */
+       if (*buffer == '#')
+           continue;
+
+       /* find the first white-space character after the filename */
+       for (symname = buffer; *symname && !isspace(*symname); symname++);
+
+       /* Now find the first non-white-space character */
+       if (*symname) {
+           *symname = '\0';
+           symname++;
+           while (*symname && isspace(*symname))
+               symname++;
+       }
+
+       if (! *symname)
+           symname = MECH_SYM;
+       else {
+         /* Find the end of the symname and make sure it is NULL-terminated */
+         for (endp = symname; *endp && !isspace(*endp); endp++);
+         if (*endp)
+           *endp = '\0';
+       }
+
+       if ((dl = dlopen(buffer, RTLD_NOW)) == NULL) {
+               /* for debugging only */
+               fprintf(stderr,"can't open %s: %s\n",buffer, dlerror());
+               continue;
+       }
+
+       if ((sym = (gss_mechanism (*)(void))dlsym(dl, symname)) == NULL) {
+           dlclose(dl);
+           continue;
+       }
+
+       /* Call the symbol to get the mechanism table */
+       mech = sym();
+
+       /* And add the mechanism (or close the shared library) */
+       if (mech)
+           add_mechanism (mech, 1);
+       else
+           dlclose(dl);
+
+    } /* while */
+
+    return;
+}
+#endif /* USE_SOLARIS_SHARED_LIBRARIES */
+
+#ifdef USE_LINUX_SHARED_LIBRARIES
+extern gss_mechanism internal_krb5_gss_initialize(void *dl);
+
+/*
+ * read the configuration file to find out what mechanisms to
+ * load, load them, and then load the mechanism defitions in
+ * and add the mechanisms
+ */
+static void linux_initialize ()
+{
+    char buffer[BUFSIZ], *filename, *symname, *endp, *err_string;
+    FILE *conffile;
+    void *dl;
+    gss_mechanism (*sym)(void), mech;
+
+    if ((filename = getenv("GSSAPI_MECH_CONF")) == NULL)
+       filename = MECH_CONF;
+
+    if ((conffile = fopen(filename, "r")) == NULL) {
+               fprintf(stderr,"fatal error: unable to open %s:"
+                       " errno %d (%s)\n", filename, errno, strerror(errno));
+               return;
+    }
+
+    while (fgets (buffer, BUFSIZ, conffile) != NULL) {
+       /* ignore lines beginning with # */
+       if (*buffer == '#')
+           continue;
+
+       /* find the first white-space character after the filename */
+       for (symname = buffer; *symname && !isspace(*symname); symname++);
+
+       /* Now find the first non-white-space character */
+       if (*symname) {
+           *symname = '\0';
+           symname++;
+           while (*symname && isspace(*symname))
+               symname++;
+       }
+
+       if (! *symname)
+           symname = MECH_SYM;
+       else {
+           /* Find the end of the symname and make sure it is
+            * NULL-terminated */
+           for (endp = symname; *endp && !isspace(*endp); endp++);
+           if (*endp)
+               *endp = '\0';
+       }
+
+       if ((dl = dlopen(buffer, RTLD_NOW)) == NULL) {
+           /* for debugging only */
+           fprintf(stderr,"can't open %s: %s\n",buffer, dlerror());
+           continue;
+       }
+
+#if defined(HAVE_KRB5) && defined(HAVE_HEIMDAL)
+#error Should not have both HAVE_KRB5 and HAVE_HEIMDAL defined!!
+#endif
+
+#ifdef HAVE_KRB5
+       /* Special case for dealing with MIT krb5 mechanism */
+       if (strcmp(symname, "mechglue_internal_krb5_init") == 0) {
+#ifdef DEBUG
+           fprintf(stderr, "Using special MIT initialization\n");
+#endif
+           mech = internal_krb5_gss_initialize(dl);
+       }
+       else
+#endif
+
+#ifdef HAVE_HEIMDAL
+       /* Special case for dealing with heimdal krb5 mechanism */
+       if (strcmp(symname, "mechglue_internal_heimdal_init") == 0) {
+#ifdef DEBUG
+           fprintf(stderr, "Using special Heimdal initialization\n");
+#endif
+           mech = internal_heimdal_gss_initialize(dl);
+       }
+       else
+#endif
+       {
+           if ((sym = (gss_mechanism (*)(void))dlsym(dl, symname)) == NULL) {
+               if ((err_string = dlerror()) != NULL) {
+                   fprintf(stderr, "%s: searching for symbol '%s' in '%s'\n",
+                           err_string, symname, buffer);
+                   dlclose(dl);
+               }
+               continue;
+           }
+
+           /* Call the symbol to get the mechanism table */
+           mech = sym();
+       }
+
+       /* And add the mechanism (or close the shared library) */
+       if (mech) {
+#ifdef DEBUG
+           fprintf(stderr, "Adding mechanism for library '%s'\n", buffer);
+#endif
+           add_mechanism (mech, 1);
+       }
+       else {
+#ifdef DEBUG
+           fprintf(stderr,
+                   "Failed to initialize mechanism for library '%s'\n",
+                    buffer);
+#endif
+           dlclose(dl);
+       }
+
+    } /* while */
+
+    return;
+}
+#endif /* USE_LINUX_SHARED_LIBRARIES */
diff --git a/support/gssapi/g_inq_context.c b/support/gssapi/g_inq_context.c
new file mode 100644 (file)
index 0000000..60f0e82
--- /dev/null
@@ -0,0 +1,143 @@
+/* #ident      "@(#)g_inquire_context.c 1.2     96/01/18 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_inquire_context
+ */
+
+#include "mglueP.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+/* Last argument new for V2 */
+OM_uint32 KRB5_CALLCONV
+gss_inquire_context(
+           minor_status,
+           context_handle,
+           src_name,
+           targ_name,
+           lifetime_rec,
+           mech_type,
+           ctx_flags,
+           locally_initiated,
+           open)
+
+OM_uint32 *    minor_status;
+gss_ctx_id_t   context_handle;
+gss_name_t *   src_name;
+gss_name_t *   targ_name;
+OM_uint32 *    lifetime_rec;
+gss_OID *      mech_type;
+OM_uint32 *    ctx_flags;
+int *           locally_initiated;
+int *          open;
+
+
+{
+    gss_union_ctx_id_t ctx;
+    gss_mechanism      mech;
+    OM_uint32          status, temp_minor;
+
+    gss_initialize();
+
+    /* if the context_handle is Null, return NO_CONTEXT error */
+
+    if(context_handle == GSS_C_NO_CONTEXT)
+       return(GSS_S_NO_CONTEXT);
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    ctx = (gss_union_ctx_id_t) context_handle;
+    mech = __gss_get_mechanism (ctx->mech_type);
+
+    if (!mech || !mech->gss_inquire_context || !mech->gss_display_name) {
+       return(GSS_S_NO_CONTEXT);
+
+    }
+
+    status = mech->gss_inquire_context(
+#ifdef USE_MECH_CONTEXT
+                       mech->context,
+#endif
+                       minor_status,
+                       ctx->internal_ctx_id,
+                       src_name,
+                       targ_name,
+                       lifetime_rec,
+                       mech_type,
+                       ctx_flags,
+                       locally_initiated,
+                       open);
+
+    if (status != GSS_S_COMPLETE) {
+       return status;
+    }
+
+    /* need to convert names */
+
+    if (src_name) {
+           status = __gss_convert_name_to_union_name(minor_status, mech,
+                                                     *src_name, src_name);
+
+           if (status != GSS_S_COMPLETE) {
+#ifdef USE_MECH_CONTEXT
+               (void) mech->gss_release_name(mech->context,
+#else
+               (void) mech->gss_release_name(
+#endif
+                                               &temp_minor, src_name);
+#ifdef USE_MECH_CONTEXT
+               (void) mech->gss_release_name(mech->context,
+#else
+               (void) mech->gss_release_name(
+#endif
+                                               &temp_minor, targ_name);
+               if (mech_type) {
+                               mech_gss_release_oid(&temp_minor, mech_type,
+                                                       mech);
+               }
+               return (GSS_S_FAILURE);
+           }
+
+    }
+
+    if (targ_name) {
+           status = __gss_convert_name_to_union_name(minor_status, mech,
+                                                     *targ_name, targ_name);
+
+           if (status != GSS_S_COMPLETE) {
+               if (mech_type) {
+                       mech_gss_release_oid(&temp_minor, mech_type, mech);
+               }
+               return (GSS_S_FAILURE);
+           }
+    }
+
+    return(GSS_S_COMPLETE);
+}
+
diff --git a/support/gssapi/g_inq_cred.c b/support/gssapi/g_inq_cred.c
new file mode 100644 (file)
index 0000000..6671f70
--- /dev/null
@@ -0,0 +1,199 @@
+/* #ident  "@(#)gss_inquire_cred.c 1.9     95/08/02 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_inquire_cred
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <time.h>
+
+OM_uint32 KRB5_CALLCONV
+gss_inquire_cred(minor_status,
+                 cred_handle,
+                 name,
+                 lifetime,
+                cred_usage,
+                 mechanisms)
+
+OM_uint32 *            minor_status;
+gss_cred_id_t          cred_handle;
+gss_name_t *           name;
+OM_uint32 *            lifetime;
+int *                  cred_usage;
+gss_OID_set *          mechanisms;
+
+{
+    OM_uint32          status, elapsed_time, temp_minor_status;
+    gss_union_cred_t   union_cred;
+    gss_mechanism      mech;
+    gss_name_t         internal_name;
+    int                        i;
+
+    gss_initialize();
+
+    if (cred_handle == GSS_C_NO_CREDENTIAL) {
+       /*
+        * No credential was supplied. This means we can't get a mechanism
+        * pointer to call the mechanism specific gss_inquire_cred.
+        * So, call get_mechanism with an arguement of GSS_C_NULL_OID.
+        * get_mechanism will return the first mechanism in the mech
+        * array, which becomes the default mechanism.
+        */
+
+       if ((mech = __gss_get_mechanism(GSS_C_NULL_OID)) == NULL)
+           return(GSS_S_NO_CRED);
+
+       if (!mech->gss_inquire_cred)
+               return (GSS_S_FAILURE);
+
+#ifdef USE_MECH_CONTEXT
+       status = mech->gss_inquire_cred(mech->context, minor_status,
+#else
+       status = mech->gss_inquire_cred(minor_status,
+#endif
+                                       GSS_C_NO_CREDENTIAL,
+                                       name ? &internal_name : NULL,
+                                       lifetime, cred_usage, mechanisms);
+
+       if (status != GSS_S_COMPLETE)
+           return(status);
+
+       if (name) {
+           /*
+            * Convert internal_name into a union_name equivalent.
+            */
+           status = __gss_convert_name_to_union_name(&temp_minor_status,
+                                                     mech, internal_name,
+                                                     name);
+           if (status != GSS_S_COMPLETE) {
+               if (minor_status)
+                   *minor_status = temp_minor_status;
+               __gss_release_internal_name(&temp_minor_status,
+                                           &mech->mech_type, &internal_name);
+               return (status);
+           }
+       }
+       return(GSS_S_COMPLETE);
+    }
+
+    /* get the cred_handle cast as a union_credentials structure */
+
+    union_cred = (gss_union_cred_t) cred_handle;
+
+    /*
+     * get the information out of the union_cred structure that was
+     * placed there during gss_acquire_cred.
+     */
+
+    if(cred_usage != NULL)
+       *cred_usage = union_cred->auxinfo.cred_usage;
+
+    if(lifetime != NULL) {
+       elapsed_time = time(0) - union_cred->auxinfo.creation_time;
+       *lifetime = union_cred->auxinfo.time_rec < elapsed_time ? 0 :
+       union_cred->auxinfo.time_rec - elapsed_time;
+    }
+
+    /*
+     * if name is non_null,
+     * call gss_import_name(), giving it the printable name held within
+     * union_cred in order to get an internal name to pass back to the
+     * caller. If this call fails, return failure to our caller.
+     */
+
+    if(name != NULL)
+       if(gss_import_name(&temp_minor_status,
+                          &union_cred->auxinfo.name,
+                          union_cred->auxinfo.name_type,
+                          name) != GSS_S_COMPLETE)
+           return(GSS_S_DEFECTIVE_CREDENTIAL);
+
+    /*
+     * copy the mechanism set in union_cred into an OID set and return in
+     * the mechanisms parameter.
+     */
+
+    if(mechanisms != NULL) {
+
+       *mechanisms = (gss_OID_set) malloc(sizeof(gss_OID_set_desc));
+
+       (*mechanisms)->count = union_cred->count;
+       (*mechanisms)->elements =
+           (gss_OID) malloc(sizeof(gss_OID_desc) *
+                            union_cred->count);
+
+       for(i=0; i < union_cred->count; i++) {
+           (*mechanisms)->elements[i].length =
+               union_cred->mechs_array[i].length;
+           (*mechanisms)->elements[i].elements = (void *)
+               malloc(union_cred->mechs_array[i].length);
+           memcpy((*mechanisms)->elements[i].elements,
+                  union_cred->mechs_array[i].elements,
+                  union_cred->mechs_array[i].length);
+       }
+    }
+
+    return(GSS_S_COMPLETE);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_inquire_cred_by_mech(minor_status, cred_handle, mech_type, name,
+                        initiator_lifetime, acceptor_lifetime, cred_usage)
+    OM_uint32          *minor_status;
+    gss_cred_id_t      cred_handle;
+    gss_OID            mech_type;
+    gss_name_t         *name;
+    OM_uint32          *initiator_lifetime;
+    OM_uint32          *acceptor_lifetime;
+    gss_cred_usage_t *cred_usage;
+{
+    gss_union_cred_t   union_cred;
+    gss_cred_id_t      mech_cred;
+    gss_mechanism      mech;
+
+    mech = __gss_get_mechanism (mech_type);
+    if (!mech)
+       return (GSS_S_BAD_MECH);
+    if (!mech->gss_inquire_cred_by_mech)
+       return (GSS_S_BAD_BINDINGS);
+
+    union_cred = (gss_union_cred_t) cred_handle;
+    mech_cred = __gss_get_mechanism_cred(union_cred, mech_type);
+
+#ifdef USE_MECH_CONTEXT
+    return (mech->gss_inquire_cred_by_mech(mech->context, minor_status,
+#else
+    return (mech->gss_inquire_cred_by_mech(minor_status,
+#endif
+                                          mech_cred, mech_type,
+                                          name, initiator_lifetime,
+                                          acceptor_lifetime, cred_usage));
+}
+
diff --git a/support/gssapi/g_inq_names.c b/support/gssapi/g_inq_names.c
new file mode 100644 (file)
index 0000000..cfcb27d
--- /dev/null
@@ -0,0 +1,69 @@
+/* #ident      "@(#)g_inquire_names.c 1.1     95/12/19 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_inquire_context
+ */
+
+#include "mglueP.h"
+
+/* Last argument new for V2 */
+OM_uint32 KRB5_CALLCONV
+gss_inquire_names_for_mech(minor_status, mechanism, name_types)
+
+OM_uint32 *    minor_status;
+gss_OID        mechanism;
+gss_OID_set *  name_types;
+
+{
+    OM_uint32          status;
+    gss_mechanism      mech;
+
+    gss_initialize();
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    mech = __gss_get_mechanism (mechanism);
+
+    if (mech) {
+
+       if (mech->gss_inquire_names_for_mech)
+           status = mech->gss_inquire_names_for_mech(
+#ifdef USE_MECH_CONTEXT
+                               mech->context,
+#endif
+                               minor_status,
+                               mechanism,
+                               name_types);
+       else
+           status = GSS_S_BAD_BINDINGS;
+
+       return(status);
+    }
+
+    return(GSS_S_NO_CONTEXT);
+}
diff --git a/support/gssapi/g_mechname.c b/support/gssapi/g_mechname.c
new file mode 100644 (file)
index 0000000..4f0a013
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * g_mechname.c --- registry of mechanism-specific name types
+ *
+ * This file contains a registry of mechanism-specific name types.  It
+ * is used to determine which name types not should be lazy evaluated,
+ * but rather evaluated on the spot.
+ */
+
+#include "mglueP.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#define g_OID_equal(o1,o2) \
+   (((o1)->length == (o2)->length) && \
+    (memcmp((o1)->elements,(o2)->elements,(int) (o1)->length) == 0))
+
+static gss_mech_spec_name name_list = NULL;
+
+/*
+ * generic searching helper function.
+ */
+static gss_mech_spec_name search_mech_spec(name_type)
+    gss_OID name_type;
+{
+    gss_mech_spec_name p;
+
+    for (p = name_list; p; p = p->next) {
+       if (g_OID_equal(name_type, p->name_type))
+           return p;
+    }
+    return NULL;
+}
+
+/*
+ * Given a name_type, if it is specific to a mechanism, return the
+ * mechanism OID.  Otherwise, return NULL.
+ */
+gss_OID gss_find_mechanism_from_name_type(name_type)
+    gss_OID name_type;
+{
+    gss_mech_spec_name p;
+
+    p = search_mech_spec(name_type);
+    if (!p)
+       return NULL;
+    return p->mech;
+}
+
+/*
+ * This function adds a (name_type, mechanism) pair to the
+ * mechanism-specific name type registry.  If an entry for the
+ * name_type already exists, then zero out the mechanism entry.
+ * Otherwise, enter the pair into the registry.
+ */
+OM_uint32
+gss_add_mech_name_type(minor_status, name_type, mech)
+    OM_uint32  *minor_status;
+    gss_OID    name_type;
+    gss_OID    mech;
+{
+    OM_uint32  major_status, tmp;
+    gss_mech_spec_name p;
+
+    p = search_mech_spec(name_type);
+    if (p) {
+       /*
+        * We found an entry for this name type; mark it as not being
+        * a mechanism-specific name type.
+        */
+       if (p->mech) {
+           if (!g_OID_equal(mech, p->mech)) {
+               generic_gss_release_oid(minor_status, &p->mech);
+               p->mech = 0;
+           }
+       }
+       return GSS_S_COMPLETE;
+    }
+    p = malloc(sizeof(gss_mech_spec_name_desc));
+    if (!p) {
+       *minor_status = ENOMEM;
+       goto allocation_failure;
+    }
+    p->name_type = 0;
+    p->mech = 0;
+
+    major_status = generic_gss_copy_oid(minor_status, name_type,
+                                       &p->name_type);
+    if (major_status)
+       goto allocation_failure;
+    major_status = generic_gss_copy_oid(minor_status, mech,
+                                       &p->mech);
+    if (major_status)
+       goto allocation_failure;
+
+    p->next = name_list;
+    p->prev = 0;
+    name_list = p;
+
+    return GSS_S_COMPLETE;
+
+allocation_failure:
+    if (p) {
+       if (p->mech)
+           generic_gss_release_oid(&tmp, &p->mech);
+       if (p->name_type)
+           generic_gss_release_oid(&tmp, &p->name_type);
+       free(p);
+    }
+    return GSS_S_FAILURE;
+}
+
diff --git a/support/gssapi/g_mit_krb5_mech.c b/support/gssapi/g_mit_krb5_mech.c
new file mode 100644 (file)
index 0000000..1caa8d2
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ *  g_mit_krb5_mech.c
+ *
+ *  Copyright (c) 2004 The Regents of the University of Michigan.
+ *  All rights reserved.
+ *
+ *  Kevin Coffman <kwc@umich.edu>
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *  3. Neither the name of the University nor the names of its
+ *     contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <dlfcn.h>
+#include "mglueP.h"
+
+/*
+ * Table of function names that we need to locate within a mechanism's
+ * shared library if it does not support the xxx_gss_initialize function.
+ */
+static char *glue_func_names[] = {
+       "gss_acquire_cred",
+       "gss_release_cred",
+       "gss_init_sec_context",
+       "gss_accept_sec_context",
+       "gss_process_context_token",
+       "gss_delete_sec_context",
+       "gss_context_time",
+       "gss_sign",
+       "gss_verify",
+       "gss_seal",
+       "gss_unseal",
+       "gss_display_status",
+       "gss_indicate_mechs",
+       "gss_compare_name",
+       "gss_display_name",
+       "gss_import_name",
+       "gss_release_name",
+       "gss_inquire_cred",
+       "gss_add_cred",
+       "gss_export_sec_context",
+       "gss_import_sec_context",
+       "gss_inquire_cred_by_mech",
+       "gss_inquire_names_for_mech",
+       "gss_inquire_context",
+       "gss_internal_release_oid",
+       "gss_wrap_size_limit",
+       "pname_to_uid",
+       "gss_duplicate_name",
+       "gss_set_allowable_enctypes",
+       "gss_verify_mic",
+       NULL
+};
+
+#ifdef HAVE_KRB5
+/*
+ * The MIT code does not support the krb5_gss_initialize function, so
+ * we need to locate the functions within the gssapi_krb5.so library
+ * and fill in this structure.
+ */
+static struct gss_config mit_krb5_mechanism = {
+       {9, "\052\206\110\206\367\022\001\002\002"},
+       NULL,           /* mechanism context -- we don't currently use this */
+       NULL,           /* gss_acquire_cred */
+       NULL,           /* gss_release_cred */
+       NULL,           /* gss_init_sec_context */
+       NULL,           /* gss_accept_sec_context */
+       NULL,           /* gss_process_context_token */
+       NULL,           /* gss_delete_sec_context */
+       NULL,           /* gss_context_time */
+       NULL,           /* gss_sign */
+       NULL,           /* gss_verify */
+       NULL,           /* gss_seal */
+       NULL,           /* gss_unseal */
+       NULL,           /* gss_display_status */
+       NULL,           /* gss_indicate_mechs */
+       NULL,           /* gss_compare_name */
+       NULL,           /* gss_display_name */
+       NULL,           /* gss_import_name */
+       NULL,           /* gss_release_name */
+       NULL,           /* gss_inquire_cred */
+       NULL,           /* gss_add_cred */
+       NULL,           /* gss_export_sec_context */
+       NULL,           /* gss_import_sec_context */
+       NULL,           /* gss_inquire_cred_by_mech */
+       NULL,           /* gss_inquire_names_for_mech */
+       NULL,           /* gss_inquire_context */
+       NULL,           /* gss_internal_release_oid */
+       NULL,           /* gss_wrap_size_limit */
+       NULL,           /* pname_to_uid */
+       NULL,           /* gss_duplicate_name */
+       NULL,           /* gss_set_allowable_enctypes */
+       NULL,           /* gss_verify_mic */
+};
+#endif
+
+#ifdef HAVE_HEIMDAL
+/*
+ * The heimdal code does not support the krb5_gss_initialize function, so
+ * we need to locate the functions within the libgssapi.so library
+ * and fill in this structure.
+ */
+static struct gss_config heimdal_krb5_mechanism = {
+       {9, "\052\206\110\206\367\022\001\002\002"},
+       NULL,           /* mechanism context -- we don't currently use this */
+       NULL,           /* gss_acquire_cred */
+       NULL,           /* gss_release_cred */
+       NULL,           /* gss_init_sec_context */
+       NULL,           /* gss_accept_sec_context */
+       NULL,           /* gss_process_context_token */
+       NULL,           /* gss_delete_sec_context */
+       NULL,           /* gss_context_time */
+       NULL,           /* gss_sign */
+       NULL,           /* gss_verify */
+       NULL,           /* gss_seal */
+       NULL,           /* gss_unseal */
+       NULL,           /* gss_display_status */
+       NULL,           /* gss_indicate_mechs */
+       NULL,           /* gss_compare_name */
+       NULL,           /* gss_display_name */
+       NULL,           /* gss_import_name */
+       NULL,           /* gss_release_name */
+       NULL,           /* gss_inquire_cred */
+       NULL,           /* gss_add_cred */
+       NULL,           /* gss_export_sec_context */
+       NULL,           /* gss_import_sec_context */
+       NULL,           /* gss_inquire_cred_by_mech */
+       NULL,           /* gss_inquire_names_for_mech */
+       NULL,           /* gss_inquire_context */
+       NULL,           /* gss_internal_release_oid */
+       NULL,           /* gss_wrap_size_limit */
+       NULL,           /* pname_to_uid */
+       NULL,           /* gss_duplicate_name */
+       NULL,           /* gss_set_allowable_enctypes */
+       NULL,           /* gss_verify_mic */
+};
+#endif
+
+
+/*
+ * Given a handle to a dynamic library (dl) and a symbol
+ * name (symname), return its address.  Returns -1 if the
+ * symbol cannot be located.  (Note that the value of the
+ * symbol could be NULL, which is valid.)
+ */
+void *
+locate_symbol(void *dl, char *symname, char *prefix)
+{
+       void *sym;
+       const char *err_string;
+       char fullname[256];
+
+       snprintf(fullname, sizeof(fullname), "%s%s", prefix, symname);
+
+       if ((sym = dlsym(dl, fullname)) == NULL) {
+               if ((sym = dlsym(dl, symname)) == NULL) {
+                       if ((err_string = dlerror()) != NULL) {
+                               return (void *)-1;
+                       }
+                       else {
+                               return NULL;
+                       }
+               }
+       }
+       return sym;
+}
+
+#ifdef HAVE_KRB5
+/*
+ * Locate all the symbols in the MIT gssapi library and
+ * fill in the gss_config (gss_mechanism) structure.
+ */
+gss_mechanism
+internal_krb5_gss_initialize(void *dl)
+{
+       char *fname;
+       void *p;
+       void **fptr;
+       int i;
+       static int mit_krb5_initialized = 0;
+
+       if (mit_krb5_initialized)
+               return (&mit_krb5_mechanism);
+
+       fptr = (void *) &mit_krb5_mechanism.gss_acquire_cred;
+
+
+       for (i = 0, fname = glue_func_names[i];
+            fname;
+            i++, fname = glue_func_names[i]) {
+               if ((p = locate_symbol(dl, fname, "krb5_")) != (void *)-1) {
+                       *fptr++ = p;
+               }
+               else {
+                       *fptr++ = NULL;
+               }
+       }
+       if (mit_krb5_mechanism.gss_internal_release_oid == NULL ||
+           mit_krb5_mechanism.gss_internal_release_oid == (void *) -1) {
+           fprintf(stderr, "WARNING: unable to locate function "
+               "krb5_gss_internal_release_oid in krb5 mechanism library: "
+               "there will be problems if multiple mechanisms are used!\n");
+           p = locate_symbol(dl, "krb5_gss_release_oid", "");
+           if (p == NULL || p == (void *) -1) {
+               fprintf(stderr, "ERROR: Unable to locate function "
+                       "krb5_gss_internal_release_oid or "
+                       "krb5_gss_release_oid in krb5 mechanism library\n");
+               return NULL;
+           }
+       }
+#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
+       /*
+        * Special case for set_allowable_enctypes which has a different
+        * name format than the rest of the gss routines :-/
+        */
+       if ((p = locate_symbol(dl, "gss_krb5_set_allowable_enctypes", ""))
+                                                       != (void *)-1) {
+               mit_krb5_mechanism.gss_set_allowable_enctypes = p;
+       }
+#endif
+       mit_krb5_initialized = 1;
+       return (&mit_krb5_mechanism);
+}
+#endif
+
+#ifdef HAVE_HEIMDAL
+/*
+ * Locate all the symbols in the MIT gssapi library and
+ * fill in the gss_config (gss_mechanism) structure.
+ */
+gss_mechanism
+internal_heimdal_gss_initialize(void *dl)
+{
+       char *fname;
+       void *p;
+       void **fptr;
+       int i;
+       static int heimdal_krb5_initialized = 0;
+
+       if (heimdal_krb5_initialized)
+               return (&heimdal_krb5_mechanism);
+
+       fptr = (void *) &heimdal_krb5_mechanism.gss_acquire_cred;
+
+
+       for (i = 0, fname = glue_func_names[i];
+            fname;
+            i++, fname = glue_func_names[i]) {
+               if ((p = locate_symbol(dl, fname, "")) != (void *)-1) {
+                       *fptr++ = p;
+               }
+               else {
+printf("Failed to locate function '%s' !!!\n", fname);
+                       *fptr++ = NULL;
+               }
+       }
+       if (heimdal_krb5_mechanism.gss_internal_release_oid == NULL ||
+           heimdal_krb5_mechanism.gss_internal_release_oid == (void *) -1) {
+           fprintf(stderr, "WARNING: unable to locate function "
+               "gss_internal_release_oid in krb5 mechanism library: "
+               "there will be problems if multiple mechanisms are used!\n");
+           p = locate_symbol(dl, "krb5_gss_release_oid", "");
+           if (p == NULL || p == (void *) -1) {
+               fprintf(stderr, "ERROR: Unable to locate function "
+                       "gss_internal_release_oid or "
+                       "gss_release_oid in krb5 mechanism library\n");
+               return NULL;
+           }
+       }
+       heimdal_krb5_initialized = 1;
+       return (&heimdal_krb5_mechanism);
+}
+#endif
diff --git a/support/gssapi/g_oid_ops.c b/support/gssapi/g_oid_ops.c
new file mode 100644 (file)
index 0000000..da0d61a
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * lib/gssapi/mechglue/g_oid_ops.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * oid_ops.c - GSS-API V2 interfaces to manipulate OIDs
+ */
+
+#include <stdio.h>
+#include "mglueP.h"
+/* should include to get protos #include "../generic/gssapiP_generic.h" */
+
+extern gss_mechanism *__gss_mechs_array;
+
+OM_uint32 KRB5_CALLCONV
+gss_release_oid(minor_status, oid)
+    OM_uint32  *minor_status;
+    gss_OID    *oid;
+{
+    int i;
+    OM_uint32   major_status;
+
+    /* first call the gss_internal_release_oid for each mechanism
+     * until one returns success. gss_internal_release_oid will only return
+     * success when the OID was recognized as an internal mechanism OID.
+     * if no mechanisms recognize the OID, then call the generic version.
+     */
+
+    for(i=0; __gss_mechs_array[i]->mech_type.length !=0; i++) {
+        if (__gss_mechs_array[i]->gss_internal_release_oid) {
+           major_status = __gss_mechs_array[i]->gss_internal_release_oid(
+#ifdef USE_MECH_CONTEXT
+                                           __gss_mechs_array[i]->context,
+#endif
+                                           minor_status,
+                                           oid);
+#ifdef DEBUG
+           fprintf(stderr, "gss_release_oid (glue): mech returned 0x%08x\n",
+                   major_status);
+#endif
+           if (major_status == GSS_S_COMPLETE) {
+               return (GSS_S_COMPLETE);
+           }
+       }
+    }
+
+#ifdef DEBUG
+    fprintf(stderr, "gss_release_oid (glue): calling "
+           "generic_gss_release_oid with oid %p (*oid %p)\n", oid, *oid);
+#endif
+    return generic_gss_release_oid(minor_status, oid);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_create_empty_oid_set(minor_status, oid_set)
+    OM_uint32  *minor_status;
+    gss_OID_set        *oid_set;
+{
+       return generic_gss_create_empty_oid_set(minor_status, oid_set);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_add_oid_set_member(minor_status, member_oid, oid_set)
+    OM_uint32  *minor_status;
+    gss_OID    member_oid;
+    gss_OID_set        *oid_set;
+{
+     return generic_gss_add_oid_set_member(minor_status, member_oid, oid_set);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_test_oid_set_member(minor_status, member, set, present)
+    OM_uint32  *minor_status;
+    gss_OID    member;
+    gss_OID_set        set;
+    int                *present;
+{
+    return generic_gss_test_oid_set_member(minor_status, member, set, present);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_oid_to_str(minor_status, oid, oid_str)
+    OM_uint32          *minor_status;
+    gss_OID            oid;
+    gss_buffer_t       oid_str;
+{
+    return generic_gss_oid_to_str(minor_status, oid, oid_str);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_str_to_oid(minor_status, oid_str, oid)
+    OM_uint32          *minor_status;
+    gss_buffer_t       oid_str;
+    gss_OID            *oid;
+{
+    return generic_gss_str_to_oid(minor_status, oid_str, oid);
+}
+
diff --git a/support/gssapi/g_process_context.c b/support/gssapi/g_process_context.c
new file mode 100644 (file)
index 0000000..322d597
--- /dev/null
@@ -0,0 +1,75 @@
+/* #ident  "@(#)gss_process_context.c 1.9     95/08/07 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine gss_process_context
+ */
+
+#include "mglueP.h"
+
+OM_uint32 KRB5_CALLCONV
+gss_process_context_token (minor_status,
+                           context_handle,
+                           token_buffer)
+
+OM_uint32 *            minor_status;
+gss_ctx_id_t           context_handle;
+gss_buffer_t           token_buffer;
+
+{
+    OM_uint32          status;
+    gss_union_ctx_id_t ctx;
+    gss_mechanism      mech;
+
+    gss_initialize();
+
+    if (context_handle == GSS_C_NO_CONTEXT)
+       return GSS_S_NO_CONTEXT;
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    ctx = (gss_union_ctx_id_t) context_handle;
+    mech = __gss_get_mechanism (ctx->mech_type);
+
+    if (mech) {
+
+       if (mech->gss_process_context_token)
+           status = mech->gss_process_context_token(
+#ifdef USE_MECH_CONTEXT
+                                                   mech->context,
+#endif
+                                                   minor_status,
+                                                   ctx->internal_ctx_id,
+                                                   token_buffer);
+       else
+           status = GSS_S_BAD_BINDINGS;
+
+       return(status);
+    }
+
+    return(GSS_S_NO_CONTEXT);
+}
diff --git a/support/gssapi/g_rel_buffer.c b/support/gssapi/g_rel_buffer.c
new file mode 100644 (file)
index 0000000..c1104fd
--- /dev/null
@@ -0,0 +1,58 @@
+/* #ident  "@(#)g_rel_buffer.c 1.2     96/02/06 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_release_buffer
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+OM_uint32 KRB5_CALLCONV
+gss_release_buffer (minor_status,
+                   buffer)
+
+OM_uint32 *            minor_status;
+gss_buffer_t           buffer;
+{
+    if (minor_status)
+       *minor_status = 0;
+
+    /* if buffer is NULL, return */
+
+    if(buffer == GSS_C_NO_BUFFER)
+       return(GSS_S_COMPLETE);
+
+    if ((buffer->length) &&
+       (buffer->value)) {
+           free(buffer->value);
+           buffer->length = 0;
+           buffer->value = NULL;
+    }
+
+    return (GSS_S_COMPLETE);
+}
diff --git a/support/gssapi/g_rel_cred.c b/support/gssapi/g_rel_cred.c
new file mode 100644 (file)
index 0000000..27a6d82
--- /dev/null
@@ -0,0 +1,104 @@
+/* #ident  "@(#)gss_release_cred.c 1.15     95/08/07 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_release_cred
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+OM_uint32 KRB5_CALLCONV
+gss_release_cred(minor_status,
+                 cred_handle)
+
+OM_uint32 *            minor_status;
+gss_cred_id_t *                cred_handle;
+
+{
+    OM_uint32          status, temp_status;
+    int                        j;
+    gss_union_cred_t   union_cred;
+    gss_mechanism      mech;
+
+    gss_initialize();
+
+    if (minor_status)
+       *minor_status = 0;
+
+    /* if the cred_handle is null, return a NO_CRED error */
+
+    if (cred_handle == GSS_C_NO_CREDENTIAL)
+       return(GSS_S_NO_CRED);
+
+    /*
+     * Loop through the union_cred struct, selecting the approprate
+     * underlying mechanism routine and calling it. At the end,
+     * release all of the storage taken by the union_cred struct.
+     */
+
+    union_cred = (gss_union_cred_t) *cred_handle;
+    *cred_handle = NULL;
+
+    if (union_cred == NULL)
+       return GSS_S_NO_CRED;
+
+    status = GSS_S_COMPLETE;
+
+    for(j=0; j < union_cred->count; j++) {
+
+       mech = __gss_get_mechanism (&union_cred->mechs_array[j]);
+
+       if (union_cred->mechs_array[j].elements)
+               free(union_cred->mechs_array[j].elements);
+       if (mech) {
+           if (mech->gss_release_cred) {
+               temp_status = mech->gss_release_cred
+#ifdef USE_MECH_CONTEXT
+                   (mech->context,
+#else
+                   (
+#endif
+                    minor_status,
+                    &union_cred->cred_array[j]);
+
+           if (temp_status != GSS_S_COMPLETE)
+               status = GSS_S_NO_CRED;
+
+           } else
+               status = GSS_S_NO_CRED;
+       } else
+           status = GSS_S_NO_CRED;
+    }
+
+    gss_release_buffer(minor_status, &union_cred->auxinfo.name);
+    free(union_cred->cred_array);
+    free(union_cred->mechs_array);
+    free(union_cred);
+
+    return(status);
+}
diff --git a/support/gssapi/g_rel_name.c b/support/gssapi/g_rel_name.c
new file mode 100644 (file)
index 0000000..ec5593a
--- /dev/null
@@ -0,0 +1,92 @@
+/* #ident  "@(#)gss_release_name.c 1.2     95/05/09 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_release_name
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+OM_uint32 KRB5_CALLCONV
+gss_release_name (minor_status,
+                 input_name)
+
+OM_uint32 *            minor_status;
+gss_name_t *           input_name;
+
+{
+    gss_union_name_t   union_name;
+
+    /* if input_name is NULL, return error */
+
+#ifdef DEBUG
+    fprintf(stderr, "gss_release_name: input_name %p *input_name %p\n",
+               input_name, *input_name);
+#endif
+    if (input_name == 0)
+       return(GSS_S_BAD_NAME);
+
+    /*
+     * free up the space for the external_name and then
+     * free the union_name descriptor
+     */
+
+    union_name = (gss_union_name_t) *input_name;
+    *input_name = 0;
+    *minor_status = 0;
+
+    if (union_name == GSS_C_NO_NAME)
+       return GSS_S_BAD_NAME;
+
+    if (union_name->name_type != GSS_C_NO_OID)
+       mech_gss_release_oid(minor_status, &union_name->name_type,
+               union_name->gss_mech);
+
+    free(union_name->external_name->value);
+    free(union_name->external_name);
+
+    if (union_name->mech_type) {
+#ifdef DEBUG
+       fprintf(stderr,
+               "gss_release_name: releasing internal name %p and oid %p\n",
+               union_name->mech_name, union_name->mech_type);
+#endif
+       __gss_release_internal_name(minor_status, union_name->mech_type,
+                                   &union_name->mech_name);
+       mech_gss_release_oid(minor_status, &union_name->mech_type,
+                       union_name->gss_mech);
+    }
+
+#ifdef DEBUG
+    fprintf(stderr, "gss_release_name: freeing union_name %p\n", union_name);
+#endif
+    free(union_name);
+
+    return(GSS_S_COMPLETE);
+}
diff --git a/support/gssapi/g_rel_oid_set.c b/support/gssapi/g_rel_oid_set.c
new file mode 100644 (file)
index 0000000..90430c1
--- /dev/null
@@ -0,0 +1,63 @@
+/* #ident  "@(#)gss_release_oid_set.c 1.12     95/08/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_release_oid_set
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+OM_uint32 KRB5_CALLCONV
+gss_release_oid_set (minor_status,
+                    set)
+
+OM_uint32 *            minor_status;
+gss_OID_set *          set;
+{
+   size_t index;
+   gss_OID oid;
+    if (minor_status)
+       *minor_status = 0;
+
+    if (set ==NULL)
+       return GSS_S_COMPLETE;
+
+    if (*set == GSS_C_NULL_OID_SET)
+       return(GSS_S_COMPLETE);
+
+    for (index=0; index<(*set)->count; index++) {
+      oid = &(*set)->elements[index];
+      free(oid->elements);
+    }
+    free((*set)->elements);
+    free(*set);
+
+    *set = GSS_C_NULL_OID_SET;
+
+    return(GSS_S_COMPLETE);
+}
diff --git a/support/gssapi/g_seal.c b/support/gssapi/g_seal.c
new file mode 100644 (file)
index 0000000..ebc8f2e
--- /dev/null
@@ -0,0 +1,155 @@
+/* #ident  "@(#)gss_seal.c 1.10     95/08/07 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_seal
+ */
+
+#include "mglueP.h"
+
+OM_uint32 KRB5_CALLCONV
+gss_seal (minor_status,
+          context_handle,
+          conf_req_flag,
+          qop_req,
+          input_message_buffer,
+          conf_state,
+          output_message_buffer)
+
+OM_uint32 *            minor_status;
+gss_ctx_id_t           context_handle;
+int                    conf_req_flag;
+int                    qop_req;
+gss_buffer_t           input_message_buffer;
+int *                  conf_state;
+gss_buffer_t           output_message_buffer;
+
+{
+    OM_uint32          status;
+    gss_union_ctx_id_t ctx;
+    gss_mechanism      mech;
+
+    gss_initialize();
+
+    if (context_handle == GSS_C_NO_CONTEXT)
+       return GSS_S_NO_CONTEXT;
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    ctx = (gss_union_ctx_id_t) context_handle;
+    mech = __gss_get_mechanism (ctx->mech_type);
+
+    if (mech) {
+       if (mech->gss_seal)
+           status = mech->gss_seal(
+#ifdef USE_MECH_CONTEXT
+                                   mech->context,
+#endif
+                                   minor_status,
+                                   ctx->internal_ctx_id,
+                                   conf_req_flag,
+                                   qop_req,
+                                   input_message_buffer,
+                                   conf_state,
+                                   output_message_buffer);
+       else
+           status = GSS_S_BAD_BINDINGS;
+
+       return(status);
+    }
+
+    return(GSS_S_NO_CONTEXT);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_wrap (minor_status,
+          context_handle,
+          conf_req_flag,
+          qop_req,
+          input_message_buffer,
+          conf_state,
+          output_message_buffer)
+
+OM_uint32 *            minor_status;
+gss_ctx_id_t           context_handle;
+int                    conf_req_flag;
+gss_qop_t              qop_req;
+gss_buffer_t           input_message_buffer;
+int *                  conf_state;
+gss_buffer_t           output_message_buffer;
+
+{
+       return gss_seal(minor_status, context_handle, conf_req_flag,
+                       (int) qop_req, input_message_buffer, conf_state,
+                       output_message_buffer);
+}
+
+/*
+ * New for V2
+ */
+OM_uint32 KRB5_CALLCONV
+gss_wrap_size_limit(minor_status, context_handle, conf_req_flag,
+                   qop_req, req_output_size, max_input_size)
+    OM_uint32          *minor_status;
+    gss_ctx_id_t       context_handle;
+    int                        conf_req_flag;
+    gss_qop_t          qop_req;
+    OM_uint32          req_output_size;
+    OM_uint32          *max_input_size;
+{
+    OM_uint32          status;
+    gss_union_ctx_id_t ctx;
+    gss_mechanism      mech;
+
+    gss_initialize();
+
+    if (context_handle == GSS_C_NO_CONTEXT)
+       return GSS_S_NO_CONTEXT;
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    ctx = (gss_union_ctx_id_t) context_handle;
+    mech = __gss_get_mechanism (ctx->mech_type);
+
+    if (!mech)
+       return (GSS_S_NO_CONTEXT);
+
+    if (!mech->gss_wrap_size_limit)
+       return (GSS_S_BAD_BINDINGS);
+
+#ifdef USE_MECH_CONTEXT
+    status = mech->gss_wrap_size_limit(mech->context, minor_status,
+#else
+    status = mech->gss_wrap_size_limit(minor_status,
+#endif
+                                      context_handle, conf_req_flag, qop_req,
+                                      req_output_size, max_input_size);
+    return(status);
+}
diff --git a/support/gssapi/g_set_allowable_enctypes.c b/support/gssapi/g_set_allowable_enctypes.c
new file mode 100644 (file)
index 0000000..27c52a4
--- /dev/null
@@ -0,0 +1,81 @@
+/* #ident  "@(#)gss_set_allowable_enctype.c 1.9     95/08/02 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_set_allowable_enctypes
+ */
+
+#include "mglueP.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+OM_uint32 KRB5_CALLCONV
+gss_set_allowable_enctypes(minor_status,
+                          cred_handle,
+                          mech_type,
+                          num_ktypes,
+                          ktypes)
+
+OM_uint32 *            minor_status;
+gss_cred_id_t          cred_handle;
+gss_OID                        mech_type;
+OM_uint32              num_ktypes;
+void *                 ktypes;
+
+{
+    gss_union_cred_t   union_cred;
+    gss_mechanism      mech;
+    gss_cred_id_t      mech_cred;
+
+    gss_initialize();
+
+    if (cred_handle == GSS_C_NO_CREDENTIAL)
+       return (GSS_S_NO_CRED);
+
+    if ((mech = __gss_get_mechanism(mech_type)) == NULL)
+       return (GSS_S_BAD_MECH);
+
+    if (!mech->gss_set_allowable_enctypes)
+       return (GSS_S_FAILURE);
+
+    /* get the mechanism-specific cred handle */
+
+    union_cred = (gss_union_cred_t) cred_handle;
+    mech_cred = __gss_get_mechanism_cred(union_cred, mech_type);
+
+    if (mech_cred == GSS_C_NO_CREDENTIAL)
+       return (GSS_S_NO_CRED);
+
+    /* Call the mechanism-specific routine */
+#ifdef USE_MECH_CONTEXT
+    return (mech->gss_set_allowable_enctypes(mech->context, minor_status,
+#else
+    return (mech->gss_set_allowable_enctypes(minor_status,
+#endif
+                                            mech_cred, num_ktypes, ktypes));
+}
+
diff --git a/support/gssapi/g_sign.c b/support/gssapi/g_sign.c
new file mode 100644 (file)
index 0000000..fe3398c
--- /dev/null
@@ -0,0 +1,99 @@
+/* #ident  "@(#)gss_sign.c 1.10     95/08/07 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine gss_sign
+ */
+
+#include "mglueP.h"
+
+OM_uint32 KRB5_CALLCONV
+gss_sign (minor_status,
+          context_handle,
+          qop_req,
+          message_buffer,
+          msg_token)
+
+OM_uint32 *            minor_status;
+gss_ctx_id_t           context_handle;
+int                    qop_req;
+gss_buffer_t           message_buffer;
+gss_buffer_t           msg_token;
+
+{
+    OM_uint32          status;
+    gss_union_ctx_id_t ctx;
+    gss_mechanism      mech;
+
+    gss_initialize();
+
+    if (context_handle == GSS_C_NO_CONTEXT)
+       return GSS_S_NO_CONTEXT;
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    ctx = (gss_union_ctx_id_t) context_handle;
+    mech = __gss_get_mechanism (ctx->mech_type);
+
+    if (mech) {
+       if (mech->gss_sign)
+           status = mech->gss_sign(
+#ifdef USE_MECH_CONTEXT
+                                   mech->context,
+#endif
+                                   minor_status,
+                                   ctx->internal_ctx_id,
+                                   qop_req,
+                                   message_buffer,
+                                   msg_token);
+       else
+           status = GSS_S_BAD_BINDINGS;
+
+       return(status);
+    }
+
+    return(GSS_S_NO_CONTEXT);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_get_mic (minor_status,
+          context_handle,
+          qop_req,
+          message_buffer,
+          msg_token)
+
+OM_uint32 *            minor_status;
+gss_ctx_id_t           context_handle;
+gss_qop_t              qop_req;
+gss_buffer_t           message_buffer;
+gss_buffer_t           msg_token;
+
+{
+       return (gss_sign(minor_status, context_handle, (int) qop_req,
+                        message_buffer, msg_token));
+}
+
diff --git a/support/gssapi/g_unseal.c b/support/gssapi/g_unseal.c
new file mode 100644 (file)
index 0000000..c274e38
--- /dev/null
@@ -0,0 +1,105 @@
+/* #ident  "@(#)gss_unseal.c 1.10     95/08/07 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine gss_unseal
+ */
+
+#include "mglueP.h"
+
+OM_uint32 KRB5_CALLCONV
+gss_unseal (minor_status,
+            context_handle,
+            input_message_buffer,
+            output_message_buffer,
+            conf_state,
+            qop_state)
+
+OM_uint32 *            minor_status;
+gss_ctx_id_t           context_handle;
+gss_buffer_t           input_message_buffer;
+gss_buffer_t           output_message_buffer;
+int *                  conf_state;
+int *                  qop_state;
+
+{
+    OM_uint32          status;
+    gss_union_ctx_id_t ctx;
+    gss_mechanism      mech;
+
+    gss_initialize();
+
+    if (context_handle == GSS_C_NO_CONTEXT)
+       return GSS_S_NO_CONTEXT;
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    ctx = (gss_union_ctx_id_t) context_handle;
+    mech = __gss_get_mechanism (ctx->mech_type);
+
+    if (mech) {
+       if (mech->gss_unseal)
+           status = mech->gss_unseal(
+#ifdef USE_MECH_CONTEXT
+                                     mech->context,
+#endif
+                                     minor_status,
+                                     ctx->internal_ctx_id,
+                                     input_message_buffer,
+                                     output_message_buffer,
+                                     conf_state,
+                                     qop_state);
+       else
+           status = GSS_S_BAD_BINDINGS;
+
+       return(status);
+    }
+
+    return(GSS_S_NO_CONTEXT);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_unwrap (minor_status,
+            context_handle,
+            input_message_buffer,
+            output_message_buffer,
+            conf_state,
+            qop_state)
+
+OM_uint32 *            minor_status;
+gss_ctx_id_t           context_handle;
+gss_buffer_t           input_message_buffer;
+gss_buffer_t           output_message_buffer;
+int *                  conf_state;
+gss_qop_t *            qop_state;
+
+{
+       return (gss_unseal(minor_status, context_handle,
+                          input_message_buffer,
+                          output_message_buffer,
+                          conf_state, (int *) qop_state));
+}
diff --git a/support/gssapi/g_verify.c b/support/gssapi/g_verify.c
new file mode 100644 (file)
index 0000000..404a6ee
--- /dev/null
@@ -0,0 +1,137 @@
+/* #ident  "@(#)gss_verify.c 1.9     95/08/07 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routine for gss_verify
+ */
+
+#include "mglueP.h"
+
+OM_uint32 KRB5_CALLCONV
+gss_verify (minor_status,
+            context_handle,
+            message_buffer,
+            token_buffer,
+            qop_state)
+
+OM_uint32 *            minor_status;
+gss_ctx_id_t           context_handle;
+gss_buffer_t           message_buffer;
+gss_buffer_t           token_buffer;
+int *                  qop_state;
+
+{
+    OM_uint32          status;
+    gss_union_ctx_id_t ctx;
+    gss_mechanism      mech;
+
+    gss_initialize();
+
+    if (context_handle == GSS_C_NO_CONTEXT)
+       return GSS_S_NO_CONTEXT;
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    ctx = (gss_union_ctx_id_t) context_handle;
+    mech = __gss_get_mechanism (ctx->mech_type);
+
+    if (mech) {
+       if (mech->gss_verify)
+           status = mech->gss_verify(
+#ifdef USE_MECH_CONTEXT
+                                     mech->context,
+#endif
+                                     minor_status,
+                                     ctx->internal_ctx_id,
+                                     message_buffer,
+                                     token_buffer,
+                                     qop_state);
+       else
+           status = GSS_S_BAD_BINDINGS;
+
+       return(status);
+    }
+
+    return(GSS_S_NO_CONTEXT);
+}
+
+OM_uint32 KRB5_CALLCONV
+gss_verify_mic (minor_status,
+            context_handle,
+            message_buffer,
+            token_buffer,
+            qop_state)
+
+OM_uint32 *            minor_status;
+gss_ctx_id_t           context_handle;
+gss_buffer_t           message_buffer;
+gss_buffer_t           token_buffer;
+gss_qop_t *            qop_state;
+
+{
+/*
+       return (gss_verify(minor_status, context_handle,
+                          message_buffer, token_buffer, (int *) qop_state));
+ */
+    OM_uint32          status;
+    gss_union_ctx_id_t ctx;
+    gss_mechanism      mech;
+
+    gss_initialize();
+
+    if (context_handle == GSS_C_NO_CONTEXT)
+       return GSS_S_NO_CONTEXT;
+
+    /*
+     * select the approprate underlying mechanism routine and
+     * call it.
+     */
+
+    ctx = (gss_union_ctx_id_t) context_handle;
+    mech = __gss_get_mechanism (ctx->mech_type);
+
+    if (mech) {
+       if (mech->gss_verify_mic) {
+           status = mech->gss_verify_mic(
+#ifdef USE_MECH_CONTEXT
+                                     mech->context,
+#endif
+                                     minor_status,
+                                     ctx->internal_ctx_id,
+                                     message_buffer,
+                                     token_buffer,
+                                     qop_state);
+           return (status);
+       }
+       else
+           return (gss_verify(minor_status, context_handle,
+                              message_buffer, token_buffer,
+                              (int *) qop_state));
+    }
+
+    return(GSS_S_NO_CONTEXT);
+}
diff --git a/support/gssapi/gen_oids.c b/support/gssapi/gen_oids.c
new file mode 100644 (file)
index 0000000..e06d60e
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "mglueP.h"
+
+/*
+ * See krb5/gssapi_krb5.c for a description of the algorithm for
+ * encoding an object identifier.
+ */
+
+/*
+ * The OID of user_name is:
+ *     iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ *     generic(1) user_name(1) = 1.2.840.113554.1.2.1.1
+ * machine_uid_name:
+ *     iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ *     generic(1) machine_uid_name(2) = 1.2.840.113554.1.2.1.2
+ * string_uid_name:
+ *     iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ *     generic(1) string_uid_name(3) = 1.2.840.113554.1.2.1.3
+ * service_name:
+ *     iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ *     generic(1) service_name(4) = 1.2.840.113554.1.2.1.4
+ * anonymous_name:
+ *     iso(1) org(3) dod(6) internet(1) security(5) nametypes(6)
+ *     gss-anonymous-name(3) = 1.3.6.1.5.6.3
+ * exported_name:
+ *     iso(1) org(3) dod(6) internet(1) security(5) nametypes(6)
+ *     gss-api-exported-name(4) = 1.3.6.1.5.6.4
+ *
+ */
+
+static const gss_OID_desc oids[] = {
+   {10, "\052\206\110\206\367\022\001\002\001\001"},
+   {10, "\052\206\110\206\367\022\001\002\001\002"},
+   {10, "\052\206\110\206\367\022\001\002\001\003"},
+   {10, "\052\206\110\206\367\022\001\002\001\004"},
+   {6,  "\053\006\001\005\006\003"},
+   {6,  "\053\006\001\005\006\004"},
+};
+
+
+/*
+ * rfc2744 defines the UPPERCASE names, the lowercase names are
+ * the original MIT names and should not be used in new applications
+ */
+const gss_OID_desc * const GSS_C_NT_USER_NAME = oids+0;
+const gss_OID_desc * const gss_nt_user_name = oids+0;
+
+const gss_OID_desc * const GSS_C_NT_MACHINE_UID_NAME = oids+1;
+const gss_OID_desc * const gss_nt_machine_uid_name = oids+1;
+
+const gss_OID_desc * const GSS_C_NT_STRING_UID_NAME = oids+2;
+const gss_OID_desc * const gss_nt_string_uid_name = oids+2;
+
+const gss_OID_desc * const GSS_C_NT_HOSTBASED_SERVICE = oids+3;
+const gss_OID_desc * const gss_nt_service_name = oids+3;
+
+const gss_OID_desc * const GSS_C_NT_ANONYMOUS = oids+4;
+
+const gss_OID_desc * const GSS_C_NT_EXPORT_NAME = oids+5;
diff --git a/support/gssapi/gssd_pname_to_uid.c b/support/gssapi/gssd_pname_to_uid.c
new file mode 100644 (file)
index 0000000..b390974
--- /dev/null
@@ -0,0 +1,71 @@
+/* #ident  "@(#)gssd_pname_to_uid.c 1.5     95/08/02 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *  glue routines that test the mech id either passed in to
+ *  gss_init_sec_contex() or gss_accept_sec_context() or within the glue
+ *  routine supported version of the security context and then call
+ *  the appropriate underlying mechanism library procedure.
+ *
+ */
+
+#include "mglueP.h"
+
+int gssd_pname_to_uid(pname, name_type, mech_type, uid)
+
+char * pname;
+gss_OID name_type;
+gss_OID mech_type;
+uid_t * uid;
+{
+    int status;
+    gss_mechanism      mech;
+
+    gss_initialize();
+
+    /*
+     * find the appropriate mechanism specific pname_to_uid procedure and
+     * call it.
+     */
+
+    mech = __gss_get_mechanism (mech_type);
+
+    if (mech) {
+       if (mech_type == GSS_C_NULL_OID)
+           mech_type = &mech->mech_type;
+
+       if (mech->pname_to_uid)
+#ifdef USE_MECH_CONTEXT
+               status = mech->pname_to_uid(mech->context,
+#else
+               status = mech->pname_to_uid(
+#endif
+                                       pname, name_type, mech_type, uid);
+       else
+           status = GSS_S_BAD_MECH;
+    } else
+       status = GSS_S_BAD_MECH;
+
+    return(status);
+}
diff --git a/support/gssapi/mechglue.h b/support/gssapi/mechglue.h
new file mode 100644 (file)
index 0000000..079ea93
--- /dev/null
@@ -0,0 +1,46 @@
+/* #ident  "@(#)mechglue.h 1.13     95/08/07 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This header contains the mechglue definitions.
+ */
+
+#ifndef _GSS_MECHGLUE_H
+#define _GSS_MECHGLUE_H
+
+#include <gssapi/gssapi.h>
+
+/********************************************************/
+/* GSSAPI Extension functions -- these functions aren't */
+/* in the GSSAPI, but they are provided in this library */
+
+int gssd_pname_to_uid (char *, gss_OID, gss_OID, uid_t *);
+void gss_initialize (void);
+OM_uint32 gss_set_allowable_enctypes( OM_uint32  *,    /* minor_status */
+                                     gss_cred_id_t,    /* cred_handle */
+                                     gss_OID,          /* mech type */
+                                     OM_uint32,        /* num_ktypes */
+                                     void *            /* ktypes */);
+
+#endif /* _GSS_MECHGLUE_H */
diff --git a/support/gssapi/mglueP.h b/support/gssapi/mglueP.h
new file mode 100644 (file)
index 0000000..362b308
--- /dev/null
@@ -0,0 +1,503 @@
+/* #ident  "@(#)mglueP.h 1.2     96/01/18 SMI" */
+
+/*
+ * This header contains the private mechglue definitions.
+ *
+ * Copyright (c) 1995, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _GSS_MECHGLUEP_H
+#define _GSS_MECHGLUEP_H
+
+#include "mechglue.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;
+
+/*
+ * Structure for holding list of mechanism-specific name types
+ */
+typedef struct gss_mech_spec_name_t {
+    gss_OID    name_type;
+    gss_OID    mech;
+    struct gss_mech_spec_name_t        *next, *prev;
+} gss_mech_spec_name_desc, *gss_mech_spec_name;
+
+/*
+ * Credential auxiliary info, used in the credential structure
+ */
+typedef struct gss_union_cred_auxinfo {
+       gss_buffer_desc         name;
+       gss_OID                 name_type;
+       time_t                  creation_time;
+       OM_uint32               time_rec;
+       int                     cred_usage;
+} gss_union_cred_auxinfo;
+
+/*
+ * Set of Credentials typed on mechanism OID
+ */
+typedef struct gss_union_cred_t {
+       int                     count;
+       gss_OID                 mechs_array;
+       gss_cred_id_t *         cred_array;
+       gss_union_cred_auxinfo  auxinfo;
+} gss_union_cred_desc, *gss_union_cred_t;
+
+/********************************************************/
+/* The Mechanism Dispatch Table -- a mechanism needs to */
+/* define one of these and provide a function to return */
+/* it to initialize the GSSAPI library                  */
+
+/*
+ * This is the definition of the mechs_array struct, which is used to
+ * define the mechs array table. This table is used to indirectly
+ * access mechanism specific versions of the gssapi routines through
+ * the routines in the glue module (gssd_mech_glue.c)
+ *
+ * This contants all of the functions defined in gssapi.h except for
+ * gss_release_buffer() and gss_release_oid_set(), which I am
+ * assuming, for now, to be equal across mechanisms.
+ */
+
+typedef struct gss_config {
+    gss_OID_desc    mech_type;
+    void *         context;
+    OM_uint32       (*gss_acquire_cred)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,              /* context */
+#endif
+                   OM_uint32*,         /* minor_status */
+                   gss_name_t,         /* desired_name */
+                   OM_uint32,          /* time_req */
+                   gss_OID_set,        /* desired_mechs */
+                   int,                /* cred_usage */
+                   gss_cred_id_t*,     /* output_cred_handle */
+                   gss_OID_set*,       /* actual_mechs */
+                   OM_uint32*          /* time_rec */
+                   );
+    OM_uint32       (*gss_release_cred)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,              /* context */
+#endif
+                   OM_uint32*,         /* minor_status */
+                   gss_cred_id_t*      /* cred_handle */
+                   );
+    OM_uint32       (*gss_init_sec_context)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,                      /* context */
+#endif
+                   OM_uint32*,                 /* minor_status */
+                   gss_cred_id_t,              /* claimant_cred_handle */
+                   gss_ctx_id_t*,              /* context_handle */
+                   gss_name_t,                 /* target_name */
+                   gss_OID,                    /* mech_type */
+                   OM_uint32,                  /* req_flags */
+                   OM_uint32,                  /* time_req */
+                   gss_channel_bindings_t,     /* input_chan_bindings */
+                   gss_buffer_t,               /* input_token */
+                   gss_OID*,                   /* actual_mech_type */
+                   gss_buffer_t,               /* output_token */
+                   OM_uint32*,                 /* ret_flags */
+                   OM_uint32*                  /* time_rec */
+                   );
+    OM_uint32       (*gss_accept_sec_context)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,                      /* context */
+#endif
+                   OM_uint32*,                 /* minor_status */
+                   gss_ctx_id_t*,              /* context_handle */
+                   gss_cred_id_t,              /* verifier_cred_handle */
+                   gss_buffer_t,               /* input_token_buffer */
+                   gss_channel_bindings_t,     /* input_chan_bindings */
+                   gss_name_t*,                /* src_name */
+                   gss_OID*,                   /* mech_type */
+                   gss_buffer_t,               /* output_token */
+                   OM_uint32*,                 /* ret_flags */
+                   OM_uint32*,                 /* time_rec */
+                   gss_cred_id_t*              /* delegated_cred_handle */
+                   );
+    OM_uint32       (*gss_process_context_token)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,              /* context */
+#endif
+                   OM_uint32*,         /* minor_status */
+                   gss_ctx_id_t,       /* context_handle */
+                   gss_buffer_t        /* token_buffer */
+                   );
+    OM_uint32       (*gss_delete_sec_context)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,              /* context */
+#endif
+                   OM_uint32*,         /* minor_status */
+                   gss_ctx_id_t*,      /* context_handle */
+                   gss_buffer_t        /* output_token */
+                   );
+    OM_uint32       (*gss_context_time)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,              /* context */
+#endif
+                   OM_uint32*,         /* minor_status */
+                   gss_ctx_id_t,       /* context_handle */
+                   OM_uint32*          /* time_rec */
+                   );
+    OM_uint32       (*gss_sign)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,              /* context */
+#endif
+                   OM_uint32*,         /* minor_status */
+                   gss_ctx_id_t,       /* context_handle */
+                   int,                /* qop_req */
+                   gss_buffer_t,       /* message_buffer */
+                   gss_buffer_t        /* message_token */
+                   );
+    OM_uint32       (*gss_verify)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,              /* context */
+#endif
+                   OM_uint32*,         /* minor_status */
+                   gss_ctx_id_t,       /* context_handle */
+                   gss_buffer_t,       /* message_buffer */
+                   gss_buffer_t,       /* token_buffer */
+                   int*                /* qop_state */
+                   );
+    OM_uint32       (*gss_seal)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,              /* context */
+#endif
+                   OM_uint32*,         /* minor_status */
+                   gss_ctx_id_t,       /* context_handle */
+                   int,                /* conf_req_flag */
+                   int,                /* qop_req */
+                   gss_buffer_t,       /* input_message_buffer */
+                   int*,               /* conf_state */
+                   gss_buffer_t        /* output_message_buffer */
+                   );
+    OM_uint32       (*gss_unseal)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,              /* context */
+#endif
+                   OM_uint32*,         /* minor_status */
+                   gss_ctx_id_t,       /* context_handle */
+                   gss_buffer_t,       /* input_message_buffer */
+                   gss_buffer_t,       /* output_message_buffer */
+                   int*,               /* conf_state */
+                   int*                /* qop_state */
+                   );
+    OM_uint32       (*gss_display_status)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,              /* context */
+#endif
+                   OM_uint32*,         /* minor_status */
+                   OM_uint32,          /* status_value */
+                   int,                /* status_type */
+                   gss_OID,            /* mech_type */
+                   OM_uint32*,         /* message_context */
+                   gss_buffer_t        /* status_string */
+                   );
+    OM_uint32       (*gss_indicate_mechs)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,              /* context */
+#endif
+                   OM_uint32*,         /* minor_status */
+                   gss_OID_set*        /* mech_set */
+                   );
+    OM_uint32       (*gss_compare_name)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,              /* context */
+#endif
+                   OM_uint32*,         /* minor_status */
+                   gss_name_t,         /* name1 */
+                   gss_name_t,         /* name2 */
+                   int*                /* name_equal */
+                   );
+    OM_uint32       (*gss_display_name)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,              /* context */
+#endif
+                   OM_uint32*,         /* minor_status */
+                   gss_name_t,         /* input_name */
+                   gss_buffer_t,       /* output_name_buffer */
+                   gss_OID*            /* output_name_type */
+                   );
+    OM_uint32       (*gss_import_name)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,              /* context */
+#endif
+                   OM_uint32*,         /* minor_status */
+                   gss_buffer_t,       /* input_name_buffer */
+                   gss_OID,            /* input_name_type */
+                   gss_name_t*         /* output_name */
+                   );
+    OM_uint32       (*gss_release_name)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,              /* context */
+#endif
+                   OM_uint32*,         /* minor_status */
+                   gss_name_t*         /* input_name */
+                   );
+    OM_uint32       (*gss_inquire_cred)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,                      /* context */
+#endif
+                   OM_uint32 *,                /* minor_status */
+                   gss_cred_id_t,              /* cred_handle */
+                   gss_name_t *,               /* name */
+                   OM_uint32 *,                /* lifetime */
+                   int *,                      /* cred_usage */
+                   gss_OID_set *               /* mechanisms */
+                   );
+    OM_uint32      (*gss_add_cred)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,              /* context */
+#endif
+                   OM_uint32 *,        /* minor_status */
+                   gss_cred_id_t,      /* input_cred_handle */
+                   gss_name_t,         /* desired_name */
+                   gss_OID,            /* desired_mech */
+                   gss_cred_usage_t,   /* cred_usage */
+                   OM_uint32,          /* initiator_time_req */
+                   OM_uint32,          /* acceptor_time_req */
+                   gss_cred_id_t *,    /* output_cred_handle */
+                   gss_OID_set *,      /* actual_mechs */
+                   OM_uint32 *,        /* initiator_time_rec */
+                   OM_uint32 *         /* acceptor_time_rec */
+                   );
+    OM_uint32      (*gss_export_sec_context)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,              /* context */
+#endif
+                   OM_uint32 *,        /* minor_status */
+                   gss_ctx_id_t *,     /* context_handle */
+                   gss_buffer_t        /* interprocess_token */
+                   );
+    OM_uint32      (*gss_import_sec_context)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void *,             /* context */
+#endif
+                   OM_uint32 *,        /* minor_status */
+                   gss_buffer_t,       /* interprocess_token */
+                   gss_ctx_id_t *      /* context_handle */
+                   );
+    OM_uint32      (*gss_inquire_cred_by_mech)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void *,             /* context */
+#endif
+                   OM_uint32 *,        /* minor_status */
+                   gss_cred_id_t,      /* cred_handle */
+                   gss_OID,            /* mech_type */
+                   gss_name_t *,       /* name */
+                   OM_uint32 *,        /* initiator_lifetime */
+                   OM_uint32 *,        /* acceptor_lifetime */
+                   gss_cred_usage_t *  /* cred_usage */
+                   );
+    OM_uint32      (*gss_inquire_names_for_mech)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void *,             /* context */
+#endif
+                   OM_uint32 *,        /* minor_status */
+                   gss_OID,            /* mechanism */
+                   gss_OID_set *       /* name_types */
+                   );
+    OM_uint32  (*gss_inquire_context)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void *,             /* context */
+#endif
+                   OM_uint32 *,        /* minor_status */
+                   gss_ctx_id_t,       /* context_handle */
+                   gss_name_t *,       /* src_name */
+                   gss_name_t *,       /* targ_name */
+                   OM_uint32 *,        /* lifetime_rec */
+                   gss_OID *,          /* mech_type */
+                   OM_uint32 *,        /* ctx_flags */
+                   int *,              /* locally_initiated */
+                   int *               /* open */
+                   );
+    OM_uint32      (*gss_internal_release_oid)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void *,             /* context */
+#endif
+                   OM_uint32 *,        /* minor_status */
+                   gss_OID *           /* OID */
+        );
+    OM_uint32       (*gss_wrap_size_limit)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void *,             /* context */
+#endif
+                   OM_uint32 *,        /* minor_status */
+                   gss_ctx_id_t,       /* context_handle */
+                   int,                /* conf_req_flag */
+                   gss_qop_t,          /* qop_req */
+                   OM_uint32,          /* req_output_size */
+                   OM_uint32 *         /* max_input_size */
+        );
+    OM_uint32       (*pname_to_uid)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void *,             /* context */
+#endif
+                   char *,             /* pname */
+                   gss_OID,            /* name type */
+                   gss_OID,            /* mech type */
+                   uid_t *             /* uid */
+                   );
+    OM_uint32        (*gss_duplicate_name)
+        (
+#ifdef USE_MECH_CONTEXT
+                    void *,            /* context */
+#endif
+                    OM_uint32  *,      /* minor_status */
+                    const gss_name_t,  /* input_name */
+                    gss_name_t *       /* dest_name */
+        );
+    OM_uint32        (*gss_set_allowable_enctypes)
+        (
+#ifdef USE_MECH_CONTEXT
+                    void *,            /* context */
+#endif
+                    OM_uint32  *,      /* minor_status */
+                   gss_cred_id_t,      /* cred_handle */
+                    OM_uint32,         /* num_ktypes */
+                    void *             /* ktypes */
+        );
+    OM_uint32       (*gss_verify_mic)
+       (
+#ifdef USE_MECH_CONTEXT
+                   void*,              /* context */
+#endif
+                   OM_uint32*,         /* minor_status */
+                   gss_ctx_id_t,       /* context_handle */
+                   gss_buffer_t,       /* message_buffer */
+                   gss_buffer_t,       /* token_buffer */
+                   int*                /* qop_state */
+                   );
+
+} *gss_mechanism;
+
+/*
+ * Generic GSSAPI names.  A name can either be a generic name, or a
+ * mechanism specific name....
+ */
+typedef struct gss_union_name_t {
+       gss_mechanism           gss_mech;
+       gss_OID                 name_type;
+       gss_buffer_t            external_name;
+       /*
+        * These last two fields are only filled in for mechanism
+        * names.
+        */
+       gss_OID                 mech_type;
+       gss_name_t              mech_name;
+} gss_union_name_desc, *gss_union_name_t;
+
+/********************************************************/
+/* Internal mechglue routines */
+
+gss_mechanism __gss_get_mechanism (gss_OID);
+OM_uint32 __gss_get_mech_type (gss_OID, gss_buffer_t);
+OM_uint32 __gss_import_internal_name (OM_uint32 *, gss_OID, gss_union_name_t,
+                                     gss_name_t *);
+OM_uint32 __gss_display_internal_name (OM_uint32 *, gss_OID, gss_name_t,
+                                      gss_buffer_t, gss_OID *);
+OM_uint32 __gss_release_internal_name (OM_uint32 *, gss_OID, gss_name_t *);
+
+OM_uint32 __gss_convert_name_to_union_name
+         (OM_uint32 *,         /* minor_status */
+          gss_mechanism,       /* mech */
+          gss_name_t,          /* internal_name */
+          gss_name_t *         /* external_name */
+          );
+gss_cred_id_t __gss_get_mechanism_cred
+         (gss_union_cred_t,    /* union_cred */
+          gss_OID              /* mech_type */
+          );
+
+OM_uint32 generic_gss_release_oid
+          (OM_uint32 *,        /* minor_status */
+           gss_OID *           /* oid */
+          );
+
+OM_uint32 mech_gss_release_oid
+          (OM_uint32 *,        /* minor_status */
+           gss_OID *,          /* oid */
+           gss_mechanism       /* gss_mech */
+          );
+
+OM_uint32 generic_gss_copy_oid
+          (OM_uint32 *,        /* minor_status */
+           gss_OID,            /* oid */
+           gss_OID *           /* new_oid */
+           );
+
+OM_uint32 generic_gss_create_empty_oid_set
+          (OM_uint32 *,        /* minor_status */
+           gss_OID_set *       /* oid_set */
+          );
+
+OM_uint32 generic_gss_add_oid_set_member
+          (OM_uint32 *,        /* minor_status */
+           gss_OID,            /* member_oid */
+           gss_OID_set *       /* oid_set */
+          );
+
+OM_uint32 generic_gss_test_oid_set_member
+          (OM_uint32 *,        /* minor_status */
+           gss_OID,            /* member */
+           gss_OID_set,        /* set */
+           int *               /* present */
+          );
+
+OM_uint32 generic_gss_oid_to_str
+ (OM_uint32 *, /* minor_status */
+           gss_OID,            /* oid */
+           gss_buffer_t        /* oid_str */
+          );
+
+OM_uint32 generic_gss_str_to_oid
+          (OM_uint32 *,        /* minor_status */
+           gss_buffer_t,       /* oid_str */
+           gss_OID *           /* oid */
+          );
+
+
+gss_OID gss_find_mechanism_from_name_type (gss_OID); /* name_type */
+
+OM_uint32 gss_add_mech_name_type
+          (OM_uint32 *,        /* minor_status */
+           gss_OID,            /* name_type */
+           gss_OID             /* mech */
+              );
+
+#endif /* _GSS_MECHGLUEP_H */
diff --git a/support/gssapi/oid_ops.c b/support/gssapi/oid_ops.c
new file mode 100644 (file)
index 0000000..ed24d58
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ * lib/gssapi/generic/oid_ops.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ *   require a specific license from the United States Government.
+ *   It is the responsibility of any person or organization contemplating
+ *   export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission.  Furthermore if you modify this software you must label
+ * your software as modified software and not distribute it in such a
+ * fashion that it might be confused with the original M.I.T. software.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose.  It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * oid_ops.c - GSS-API V2 interfaces to manipulate OIDs
+ */
+
+#include "mglueP.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+
+OM_uint32
+generic_gss_release_oid(minor_status, oid)
+    OM_uint32  *minor_status;
+    gss_OID    *oid;
+{
+    *minor_status = 0;
+#ifdef DEBUG
+    static int printed = 0;
+
+    if (!printed++)
+       fprintf(stderr, "gss_generic_release_oid (glue):\n"
+               "  GSS_C_NT_USER_NAME           %p\n"
+               "  GSS_C_NT_MACHINE_UID_NAME    %p\n"
+               "  GSS_C_NT_STRING_UID_NAME     %p\n"
+               "  GSS_C_NT_HOSTBASED_SERVICE   %p\n"
+               "  GSS_C_NT_ANONYMOUS           %p\n"
+               "  GSS_C_NT_EXPORT_NAME         %p\n",
+       GSS_C_NT_USER_NAME, GSS_C_NT_MACHINE_UID_NAME,
+       GSS_C_NT_STRING_UID_NAME, GSS_C_NT_HOSTBASED_SERVICE,
+       GSS_C_NT_ANONYMOUS, GSS_C_NT_EXPORT_NAME);
+#endif
+
+    if (*oid == GSS_C_NO_OID)
+       return(GSS_S_COMPLETE);
+
+    /*
+     * The V2 API says the following!
+     *
+     * gss_release_oid[()] will recognize any of the GSSAPI's own OID values,
+     * and will silently ignore attempts to free these OIDs; for other OIDs
+     * it will call the C free() routine for both the OID data and the
+     * descriptor.  This allows applications to freely mix their own heap-
+     * allocated OID values with OIDs returned by GSS-API.
+     */
+    if ((*oid != GSS_C_NT_USER_NAME) &&
+       (*oid != GSS_C_NT_MACHINE_UID_NAME) &&
+       (*oid != GSS_C_NT_STRING_UID_NAME) &&
+       (*oid != GSS_C_NT_HOSTBASED_SERVICE) &&
+       (*oid != GSS_C_NT_ANONYMOUS) &&
+       (*oid != GSS_C_NT_EXPORT_NAME)) {
+#ifdef DEBUG
+       fprintf(stderr, "generic_gss_release_oid (glue): freeing *oid at %p\n",
+               *oid);
+#endif
+       free((*oid)->elements);
+       free(*oid);
+    }
+    *oid = GSS_C_NO_OID;
+    return(GSS_S_COMPLETE);
+}
+
+OM_uint32
+mech_gss_release_oid(minor_status, oid, gss_mech)
+    OM_uint32  *minor_status;
+    gss_OID    *oid;
+    gss_mechanism      gss_mech;
+{
+    *minor_status = 0;
+
+#ifdef DEBUG
+       fprintf(stderr, "mech_gss_release_oid: *oid %p, gss_mech %p\n",
+               *oid, gss_mech);
+#endif
+    if (*oid == GSS_C_NO_OID)
+       return (GSS_S_COMPLETE);
+
+    if (gss_mech == NULL) {
+#ifdef DEBUG
+       fprintf(stderr, "mech_gss_release_oid: no gss_mech!\n");
+#endif
+       return (generic_gss_release_oid(minor_status, oid));
+    }
+
+    if (!gss_mech->gss_internal_release_oid) {
+#ifdef DEBUG
+       fprintf(stderr, "mech_gss_release_oid: mechanism has "
+                       "no gss_internal_release_oid function! using "
+                       "generic_gss_release_oid\n");
+#endif
+       return (generic_gss_release_oid(minor_status, oid));
+    }
+
+#ifdef DEBUG
+    fprintf(stderr, "mech_gss_release_oid: calling mechanism's "
+                       "gss_internal_release_oid\n");
+#endif
+    return (gss_mech->gss_internal_release_oid(minor_status, oid));
+}
+
+OM_uint32
+generic_gss_copy_oid(minor_status, oid, new_oid)
+       OM_uint32       *minor_status;
+       gss_OID         oid, *new_oid;
+{
+       gss_OID         p;
+
+       if (oid == GSS_C_NO_OID) {
+               *new_oid = GSS_C_NO_OID;
+               return (GSS_S_COMPLETE);
+       }
+
+       p = (gss_OID) malloc(sizeof(gss_OID_desc));
+       if (!p) {
+               *minor_status = ENOMEM;
+               return GSS_S_FAILURE;
+       }
+       p->length = oid->length;
+       p->elements = malloc(p->length);
+       if (!p->elements) {
+               free(p);
+               *minor_status = ENOMEM;
+               return GSS_S_FAILURE;
+       }
+       memcpy(p->elements, oid->elements, p->length);
+       *new_oid = p;
+       return (GSS_S_COMPLETE);
+}
+
+
+OM_uint32
+generic_gss_create_empty_oid_set(minor_status, oid_set)
+    OM_uint32  *minor_status;
+    gss_OID_set        *oid_set;
+{
+    if ((*oid_set = (gss_OID_set) malloc(sizeof(gss_OID_set_desc)))) {
+       memset(*oid_set, 0, sizeof(gss_OID_set_desc));
+       *minor_status = 0;
+       return(GSS_S_COMPLETE);
+    }
+    else {
+       *minor_status = ENOMEM;
+       return(GSS_S_FAILURE);
+    }
+}
+
+OM_uint32
+generic_gss_add_oid_set_member(minor_status, member_oid, oid_set)
+    OM_uint32  *minor_status;
+    gss_OID    member_oid;
+    gss_OID_set        *oid_set;
+{
+    gss_OID    elist;
+    gss_OID    lastel;
+
+    elist = (*oid_set)->elements;
+    /* Get an enlarged copy of the array */
+    if (((*oid_set)->elements = (gss_OID) malloc(((*oid_set)->count+1) *
+                                                 sizeof(gss_OID_desc)))) {
+       /* Copy in the old junk */
+       if (elist)
+           memcpy((*oid_set)->elements,
+                  elist,
+                  ((*oid_set)->count * sizeof(gss_OID_desc)));
+
+       /* Duplicate the input element */
+       lastel = &(*oid_set)->elements[(*oid_set)->count];
+       if ((lastel->elements =
+            (void *) malloc((size_t) member_oid->length))) {
+           /* Success - copy elements */
+           memcpy(lastel->elements, member_oid->elements,
+                  (size_t) member_oid->length);
+           /* Set length */
+           lastel->length = member_oid->length;
+
+           /* Update count */
+           (*oid_set)->count++;
+           if (elist)
+               free(elist);
+           *minor_status = 0;
+           return(GSS_S_COMPLETE);
+       }
+       else
+           free((*oid_set)->elements);
+    }
+    /* Failure - restore old contents of list */
+    (*oid_set)->elements = elist;
+    *minor_status = ENOMEM;
+    return(GSS_S_FAILURE);
+}
+
+OM_uint32
+generic_gss_test_oid_set_member(minor_status, member, set, present)
+    OM_uint32  *minor_status;
+    gss_OID    member;
+    gss_OID_set        set;
+    int                *present;
+{
+    size_t     i;
+    int                result;
+
+    result = 0;
+    for (i=0; i<set->count; i++) {
+       if ((set->elements[i].length == member->length) &&
+           !memcmp(set->elements[i].elements,
+                   member->elements,
+                   (size_t) member->length)) {
+           result = 1;
+           break;
+       }
+    }
+    *present = result;
+    *minor_status = 0;
+    return(GSS_S_COMPLETE);
+}
+
+/*
+ * OID<->string routines.  These are uuuuugly.
+ */
+OM_uint32
+generic_gss_oid_to_str(minor_status, oid, oid_str)
+    OM_uint32          *minor_status;
+    gss_OID            oid;
+    gss_buffer_t       oid_str;
+{
+    char               numstr[128];
+    unsigned long      number;
+    int                        numshift;
+    size_t             string_length;
+    size_t             i;
+    unsigned char      *cp;
+    char               *bp;
+
+    /* Decoded according to krb5/gssapi_krb5.c */
+
+    /* First determine the size of the string */
+    string_length = 0;
+    number = 0;
+    numshift = 0;
+    cp = (unsigned char *) oid->elements;
+    number = (unsigned long) cp[0];
+    sprintf(numstr, "%ld ", number/40);
+    string_length += strlen(numstr);
+    sprintf(numstr, "%ld ", number%40);
+    string_length += strlen(numstr);
+    for (i=1; i<oid->length; i++) {
+       if ( (size_t) (numshift+7) < (sizeof(unsigned long)*8)) {
+           number = (number << 7) | (cp[i] & 0x7f);
+           numshift += 7;
+       }
+       else {
+           *minor_status = EINVAL;
+           return(GSS_S_FAILURE);
+       }
+       if ((cp[i] & 0x80) == 0) {
+           sprintf(numstr, "%ld ", number);
+           string_length += strlen(numstr);
+           number = 0;
+           numshift = 0;
+       }
+    }
+    /*
+     * If we get here, we've calculated the length of "n n n ... n ".  Add 4
+     * here for "{ " and "}\0".
+     */
+    string_length += 4;
+    if ((bp = (char *) malloc(string_length))) {
+       strcpy(bp, "{ ");
+       number = (unsigned long) cp[0];
+       sprintf(numstr, "%ld ", number/40);
+       strcat(bp, numstr);
+       sprintf(numstr, "%ld ", number%40);
+       strcat(bp, numstr);
+       number = 0;
+       cp = (unsigned char *) oid->elements;
+       for (i=1; i<oid->length; i++) {
+           number = (number << 7) | (cp[i] & 0x7f);
+           if ((cp[i] & 0x80) == 0) {
+               sprintf(numstr, "%ld ", number);
+               strcat(bp, numstr);
+               number = 0;
+           }
+       }
+       strcat(bp, "}");
+       oid_str->length = strlen(bp)+1;
+       oid_str->value = (void *) bp;
+       *minor_status = 0;
+       return(GSS_S_COMPLETE);
+    }
+    *minor_status = ENOMEM;
+    return(GSS_S_FAILURE);
+}
+
+OM_uint32
+generic_gss_str_to_oid(minor_status, oid_str, oid)
+    OM_uint32          *minor_status;
+    gss_buffer_t       oid_str;
+    gss_OID            *oid;
+{
+    char       *cp, *bp, *startp;
+    int                brace;
+    long       numbuf;
+    long       onumbuf;
+    OM_uint32  nbytes;
+    int                index;
+    unsigned char *op;
+
+    brace = 0;
+    bp = (char *) oid_str->value;
+    cp = bp;
+    /* Skip over leading space */
+    while ((bp < &cp[oid_str->length]) && isspace(*bp))
+       bp++;
+    if (*bp == '{') {
+       brace = 1;
+       bp++;
+    }
+    while ((bp < &cp[oid_str->length]) && isspace(*bp))
+       bp++;
+    startp = bp;
+    nbytes = 0;
+
+    /*
+     * The first two numbers are chewed up by the first octet.
+     */
+    if (sscanf(bp, "%ld", &numbuf) != 1) {
+       *minor_status = EINVAL;
+       return(GSS_S_FAILURE);
+    }
+    while ((bp < &cp[oid_str->length]) && isdigit(*bp))
+       bp++;
+    while ((bp < &cp[oid_str->length]) && isspace(*bp))
+       bp++;
+    if (sscanf(bp, "%ld", &numbuf) != 1) {
+       *minor_status = EINVAL;
+       return(GSS_S_FAILURE);
+    }
+    while ((bp < &cp[oid_str->length]) && isdigit(*bp))
+       bp++;
+    while ((bp < &cp[oid_str->length]) && isspace(*bp))
+       bp++;
+    nbytes++;
+    while (isdigit(*bp)) {
+       if (sscanf(bp, "%ld", &numbuf) != 1) {
+           *minor_status = EINVAL;
+           return(GSS_S_FAILURE);
+       }
+       while (numbuf) {
+           nbytes++;
+           numbuf >>= 7;
+       }
+       while ((bp < &cp[oid_str->length]) && isdigit(*bp))
+           bp++;
+       while ((bp < &cp[oid_str->length]) && isspace(*bp))
+           bp++;
+    }
+    if (brace && (*bp != '}')) {
+       *minor_status = EINVAL;
+       return(GSS_S_FAILURE);
+    }
+
+    /*
+     * Phew!  We've come this far, so the syntax is good.
+     */
+    if ((*oid = (gss_OID) malloc(sizeof(gss_OID_desc)))) {
+       if (((*oid)->elements = (void *) malloc((size_t) nbytes))) {
+           (*oid)->length = nbytes;
+           op = (unsigned char *) (*oid)->elements;
+           bp = startp;
+           sscanf(bp, "%ld", &numbuf);
+           while (isdigit(*bp))
+               bp++;
+           while (isspace(*bp))
+               bp++;
+           onumbuf = 40*numbuf;
+           sscanf(bp, "%ld", &numbuf);
+           onumbuf += numbuf;
+           *op = (unsigned char) onumbuf;
+           op++;
+           while (isdigit(*bp))
+               bp++;
+           while (isspace(*bp))
+               bp++;
+           while (isdigit(*bp)) {
+               sscanf(bp, "%ld", &numbuf);
+               nbytes = 0;
+               /* Have to fill in the bytes msb-first */
+               onumbuf = numbuf;
+               while (numbuf) {
+                   nbytes++;
+                   numbuf >>= 7;
+               }
+               numbuf = onumbuf;
+               op += nbytes;
+               index = -1;
+               while (numbuf) {
+                   op[index] = (unsigned char) numbuf & 0x7f;
+                   if (index != -1)
+                       op[index] |= 0x80;
+                   index--;
+                   numbuf >>= 7;
+               }
+               while (isdigit(*bp))
+                   bp++;
+               while (isspace(*bp))
+                   bp++;
+           }
+           *minor_status = 0;
+           return(GSS_S_COMPLETE);
+       }
+       else {
+           free(*oid);
+           *oid = GSS_C_NO_OID;
+       }
+    }
+    *minor_status = ENOMEM;
+    return(GSS_S_FAILURE);
+}
+
index f8c1497..6a6a065 100644 (file)
  * but lockd from using this service.
  */
 #undef RESTRICTED_STATD
+
+/* Define this if you want support for rpcsec_gss with
+ * the MIT krb5 mechanism compiled in */
+#undef HAVE_KRB5
+
+/* Define this if you want support for rpcsec_gss with
+ * the Heimdal krb5 mechanism compiled in */
+#undef HAVE_HEIMDAL
+
+/* Define this if the Kerberos gssapi library has function
+ * gss_krb5_export_lucid_sec_context */
+#undef HAVE_LUCID_CONTEXT_SUPPORT
+
+/* Define this if the Kerberos gssapi library has function
+ * gss_krb5_set_allowable_enctypes */
+#undef HAVE_SET_ALLOWABLE_ENCTYPES
+
+/* Define this if the Kerberos gssapi library has function
+ * gss_krb5_cache_name */
+#undef HAVE_GSS_KRB5_CCACHE_NAME
diff --git a/support/include/gssapi/gssapi.h b/support/include/gssapi/gssapi.h
new file mode 100644 (file)
index 0000000..18d62db
--- /dev/null
@@ -0,0 +1,846 @@
+/* This is the gssapi.h prologue. */
+/* It contains some choice pieces of autoconf.h */
+#define SIZEOF_INT 4
+#define SIZEOF_LONG 4
+#define SIZEOF_SHORT 2
+#define HAVE_STDARG_H 1
+/* #undef HAVE_VARARGS_H */
+/* #undef HAVE_MACSOCK_H */
+#define HAVE_NETINET_IN_H 1
+#define HAVE_STDDEF_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#define HAVE_SYS_FILE_H 1
+#define HAVE_SYS_PARAM_H 1
+#define HAVE_SYS_SOCKET_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_SYS_TIME_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_UNISTD_H 1
+/* #undef HAVE_XOM_H */
+#define USE_DIRENT_H 1
+/* End of gssapi.h prologue. */
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _GSSAPI_H_
+#define _GSSAPI_H_
+
+/*
+ * Determine platform-dependent configuration.
+ */
+
+#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
+       #include <TargetConditionals.h>
+    #if TARGET_RT_MAC_CFM
+        #error "Use KfM 4.0 SDK headers for CFM compilation."
+    #endif
+
+       /* This is an API divergence in 1.2.3. This will be reconciled in 1.3, when
+       all platforms will have RFC-compliant OID declarations. */
+       #define GSS_RFC_COMPLIANT_OIDS 1
+#else
+       #define GSS_RFC_COMPLIANT_OIDS 0
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if TARGET_OS_MAC
+    #if defined(__MWERKS__)
+        #pragma import on
+        #pragma enumsalwaysint on
+    #endif
+    #pragma options align=mac68k
+#endif
+
+#if defined(_MSDOS) || defined(_WIN32)
+#include <win-mac.h>
+#endif
+
+/* #ifndef KRB5_CALLCONV */
+#define KRB5_CALLCONV
+#define KRB5_CALLCONV_C
+#define KRB5_DLLIMP
+#define GSS_DLLIMP
+#define KRB5_EXPORTVAR
+/* #endif */
+#ifndef FAR
+#define FAR
+#define NEAR
+#endif
+
+#define        GSS_SIZEOF_INT          SIZEOF_INT
+#define        GSS_SIZEOF_LONG         SIZEOF_LONG
+#define        GSS_SIZEOF_SHORT        SIZEOF_SHORT
+
+/*
+ * Make sure we have a definition for PROTOTYPE.
+ */
+#if !defined(PROTOTYPE)
+#if defined(__STDC__) || defined(__cplusplus) || defined(_MSDOS) || defined(_WIN32) || defined(__ultrix)
+#define PROTOTYPE(x) x
+#else
+#define PROTOTYPE(x) ()
+#endif
+#endif
+
+/*
+ * First, include stddef.h to get size_t defined.
+ */
+#if    HAVE_STDDEF_H
+#include <stddef.h>
+#endif /* HAVE_STDDEF_H */
+
+/*
+ * POSIX says that sys/types.h is where size_t is defined.
+ */
+#ifndef macintosh
+#include <sys/types.h>
+#endif
+
+/*
+ * If the platform supports the xom.h header file, it should be included here.
+ */
+#if    HAVE_XOM_H
+#include <xom.h>
+#endif /* HAVE_XOM_H */
+
+/*
+ * $Id: gssapi.h,v 1.1 2004/10/19 00:22:57 neilbrown Exp $
+ */
+
+/*
+ * First, define the three platform-dependent pointer types.
+ */
+
+typedef void FAR * gss_name_t;
+typedef void FAR * gss_cred_id_t;
+typedef void FAR * gss_ctx_id_t;
+
+/*
+ * The following type must be defined as the smallest natural unsigned integer
+ * supported by the platform that has at least 32 bits of precision.
+ */
+#if (GSS_SIZEOF_SHORT == 4)
+typedef unsigned short gss_uint32;
+typedef short gss_int32;
+#elif (GSS_SIZEOF_INT == 4)
+typedef unsigned int gss_uint32;
+typedef int gss_int32;
+#elif (GSS_SIZEOF_LONG == 4)
+typedef unsigned long gss_uint32;
+typedef long gss_int32;
+#endif
+
+#ifdef OM_STRING
+/*
+ * We have included the xom.h header file.  Use the definition for
+ * OM_object identifier.
+ */
+typedef OM_object_identifier   gss_OID_desc, *gss_OID;
+#else  /* OM_STRING */
+/*
+ * We can't use X/Open definitions, so roll our own.
+ */
+typedef gss_uint32     OM_uint32;
+
+typedef struct gss_OID_desc_struct {
+      OM_uint32 length;
+      void      FAR *elements;
+} gss_OID_desc, FAR *gss_OID;
+#endif /* OM_STRING */
+
+typedef struct gss_OID_set_desc_struct  {
+      size_t  count;
+      gss_OID elements;
+} gss_OID_set_desc, FAR *gss_OID_set;
+
+typedef struct gss_buffer_desc_struct {
+      size_t length;
+      void FAR *value;
+} gss_buffer_desc, FAR *gss_buffer_t;
+
+typedef struct gss_channel_bindings_struct {
+      OM_uint32 initiator_addrtype;
+      gss_buffer_desc initiator_address;
+      OM_uint32 acceptor_addrtype;
+      gss_buffer_desc acceptor_address;
+      gss_buffer_desc application_data;
+} FAR *gss_channel_bindings_t;
+
+/*
+ * For now, define a QOP-type as an OM_uint32 (pending resolution of ongoing
+ * discussions).
+ */
+typedef        OM_uint32       gss_qop_t;
+typedef        int             gss_cred_usage_t;
+
+/*
+ * Flag bits for context-level services.
+ */
+#define GSS_C_DELEG_FLAG 1
+#define GSS_C_MUTUAL_FLAG 2
+#define GSS_C_REPLAY_FLAG 4
+#define GSS_C_SEQUENCE_FLAG 8
+#define GSS_C_CONF_FLAG 16
+#define GSS_C_INTEG_FLAG 32
+#define        GSS_C_ANON_FLAG 64
+#define GSS_C_PROT_READY_FLAG 128
+#define GSS_C_TRANS_FLAG 256
+
+/*
+ * Credential usage options
+ */
+#define GSS_C_BOTH 0
+#define GSS_C_INITIATE 1
+#define GSS_C_ACCEPT 2
+
+/*
+ * Status code types for gss_display_status
+ */
+#define GSS_C_GSS_CODE 1
+#define GSS_C_MECH_CODE 2
+
+/*
+ * The constant definitions for channel-bindings address families
+ */
+#define GSS_C_AF_UNSPEC     0
+#define GSS_C_AF_LOCAL      1
+#define GSS_C_AF_INET       2
+#define GSS_C_AF_IMPLINK    3
+#define GSS_C_AF_PUP        4
+#define GSS_C_AF_CHAOS      5
+#define GSS_C_AF_NS         6
+#define GSS_C_AF_NBS        7
+#define GSS_C_AF_ECMA       8
+#define GSS_C_AF_DATAKIT    9
+#define GSS_C_AF_CCITT      10
+#define GSS_C_AF_SNA        11
+#define GSS_C_AF_DECnet     12
+#define GSS_C_AF_DLI        13
+#define GSS_C_AF_LAT        14
+#define GSS_C_AF_HYLINK     15
+#define GSS_C_AF_APPLETALK  16
+#define GSS_C_AF_BSC        17
+#define GSS_C_AF_DSS        18
+#define GSS_C_AF_OSI        19
+#define GSS_C_AF_X25        21
+
+#define GSS_C_AF_NULLADDR   255
+
+/*
+ * Various Null values.
+ */
+#define GSS_C_NO_NAME ((gss_name_t) 0)
+#define GSS_C_NO_BUFFER ((gss_buffer_t) 0)
+#define GSS_C_NO_OID ((gss_OID) 0)
+#define GSS_C_NO_OID_SET ((gss_OID_set) 0)
+#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0)
+#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0)
+#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0)
+#define GSS_C_EMPTY_BUFFER {0, NULL}
+
+/*
+ * Some alternate names for a couple of the above values.  These are defined
+ * for V1 compatibility.
+ */
+#define        GSS_C_NULL_OID          GSS_C_NO_OID
+#define        GSS_C_NULL_OID_SET      GSS_C_NO_OID_SET
+
+/*
+ * Define the default Quality of Protection for per-message services.  Note
+ * that an implementation that offers multiple levels of QOP may either reserve
+ * a value (for example zero, as assumed here) to mean "default protection", or
+ * alternatively may simply equate GSS_C_QOP_DEFAULT to a specific explicit
+ * QOP value.  However a value of 0 should always be interpreted by a GSSAPI
+ * implementation as a request for the default protection level.
+ */
+#define GSS_C_QOP_DEFAULT 0
+
+/*
+ * Expiration time of 2^32-1 seconds means infinite lifetime for a
+ * credential or security context
+ */
+#define GSS_C_INDEFINITE ((OM_uint32) 0xfffffffful)
+
+
+/* Major status codes */
+
+#define GSS_S_COMPLETE 0
+
+/*
+ * Some "helper" definitions to make the status code macros obvious.
+ */
+#define GSS_C_CALLING_ERROR_OFFSET 24
+#define GSS_C_ROUTINE_ERROR_OFFSET 16
+#define GSS_C_SUPPLEMENTARY_OFFSET 0
+#define GSS_C_CALLING_ERROR_MASK ((OM_uint32) 0377ul)
+#define GSS_C_ROUTINE_ERROR_MASK ((OM_uint32) 0377ul)
+#define GSS_C_SUPPLEMENTARY_MASK ((OM_uint32) 0177777ul)
+
+/*
+ * The macros that test status codes for error conditions.  Note that the
+ * GSS_ERROR() macro has changed slightly from the V1 GSSAPI so that it now
+ * evaluates its argument only once.
+ */
+#define GSS_CALLING_ERROR(x) \
+  ((x) & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET))
+#define GSS_ROUTINE_ERROR(x) \
+  ((x) & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))
+#define GSS_SUPPLEMENTARY_INFO(x) \
+  ((x) & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET))
+#define GSS_ERROR(x) \
+  ((x) & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \
+         (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)))
+
+/*
+ * Now the actual status code definitions
+ */
+
+/*
+ * Calling errors:
+ */
+#define GSS_S_CALL_INACCESSIBLE_READ \
+                             (((OM_uint32) 1ul) << GSS_C_CALLING_ERROR_OFFSET)
+#define GSS_S_CALL_INACCESSIBLE_WRITE \
+                             (((OM_uint32) 2ul) << GSS_C_CALLING_ERROR_OFFSET)
+#define GSS_S_CALL_BAD_STRUCTURE \
+                             (((OM_uint32) 3ul) << GSS_C_CALLING_ERROR_OFFSET)
+
+/*
+ * Routine errors:
+ */
+#define GSS_S_BAD_MECH (((OM_uint32) 1ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_NAME (((OM_uint32) 2ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_NAMETYPE (((OM_uint32) 3ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_BINDINGS (((OM_uint32) 4ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_STATUS (((OM_uint32) 5ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_SIG (((OM_uint32) 6ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_NO_CRED (((OM_uint32) 7ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_NO_CONTEXT (((OM_uint32) 8ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_DEFECTIVE_TOKEN (((OM_uint32) 9ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_DEFECTIVE_CREDENTIAL \
+     (((OM_uint32) 10ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_CREDENTIALS_EXPIRED \
+     (((OM_uint32) 11ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_CONTEXT_EXPIRED \
+     (((OM_uint32) 12ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_FAILURE (((OM_uint32) 13ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_QOP (((OM_uint32) 14ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_UNAUTHORIZED (((OM_uint32) 15ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_UNAVAILABLE (((OM_uint32) 16ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_DUPLICATE_ELEMENT \
+     (((OM_uint32) 17ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_NAME_NOT_MN \
+     (((OM_uint32) 18ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+
+/*
+ * Supplementary info bits:
+ */
+#define GSS_S_CONTINUE_NEEDED (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 0))
+#define GSS_S_DUPLICATE_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 1))
+#define GSS_S_OLD_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 2))
+#define GSS_S_UNSEQ_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 3))
+#define GSS_S_GAP_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 4))
+
+
+/*
+ * Finally, function prototypes for the GSSAPI routines.
+ */
+
+/* Reserved static storage for GSS_oids.  Comments are quotes from RFC 2744.
+ *
+ * The implementation must reserve static storage for a
+ * gss_OID_desc object containing the value
+ * {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x01"},
+ * corresponding to an object-identifier value of
+ * {iso(1) member-body(2) United States(840) mit(113554)
+ * infosys(1) gssapi(2) generic(1) user_name(1)}.  The constant
+ * GSS_C_NT_USER_NAME should be initialized to point
+ * to that gss_OID_desc.
+ */
+extern const gss_OID_desc * const GSS_C_NT_USER_NAME;
+
+/*
+ * The implementation must reserve static storage for a
+ * gss_OID_desc object containing the value
+ * {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02"},
+ * corresponding to an object-identifier value of
+ * {iso(1) member-body(2) United States(840) mit(113554)
+ * infosys(1) gssapi(2) generic(1) machine_uid_name(2)}.
+ * The constant GSS_C_NT_MACHINE_UID_NAME should be
+ * initialized to point to that gss_OID_desc.
+ */
+extern const gss_OID_desc * const GSS_C_NT_MACHINE_UID_NAME;
+
+/*
+ * The implementation must reserve static storage for a
+ * gss_OID_desc object containing the value
+ * {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03"},
+ * corresponding to an object-identifier value of
+ * {iso(1) member-body(2) United States(840) mit(113554)
+ * infosys(1) gssapi(2) generic(1) string_uid_name(3)}.
+ * The constant GSS_C_NT_STRING_UID_NAME should be
+ * initialized to point to that gss_OID_desc.
+ */
+extern const gss_OID_desc * const GSS_C_NT_STRING_UID_NAME;
+
+/*
+ * The implementation must reserve static storage for a
+ * gss_OID_desc object containing the value
+ * {6, (void *)"\x2b\x06\x01\x05\x06\x02"},
+ * corresponding to an object-identifier value of
+ * {iso(1) org(3) dod(6) internet(1) security(5)
+ * nametypes(6) gss-host-based-services(2)).  The constant
+ * GSS_C_NT_HOSTBASED_SERVICE_X should be initialized to point
+ * to that gss_OID_desc.  This is a deprecated OID value, and
+ * implementations wishing to support hostbased-service names
+ * should instead use the GSS_C_NT_HOSTBASED_SERVICE OID,
+ * defined below, to identify such names;
+ * GSS_C_NT_HOSTBASED_SERVICE_X should be accepted a synonym
+ * for GSS_C_NT_HOSTBASED_SERVICE when presented as an input
+ * parameter, but should not be emitted by GSS-API
+ * implementations
+GSS_DLLIMP extern gss_OID GSS_C_NT_HOSTBASED_SERVICE_X;
+ */
+
+/*
+ * The implementation must reserve static storage for a
+ * gss_OID_desc object containing the value
+ * {10, (void *)"\x2a\x86\x48\x86\xf7\x12"
+ *              "\x01\x02\x01\x04"}, corresponding to an
+ * object-identifier value of {iso(1) member-body(2)
+ * Unites States(840) mit(113554) infosys(1) gssapi(2)
+ * generic(1) service_name(4)}.  The constant
+ * GSS_C_NT_HOSTBASED_SERVICE should be initialized
+ * to point to that gss_OID_desc.
+ */
+extern const gss_OID_desc * const GSS_C_NT_HOSTBASED_SERVICE;
+
+/*
+ * The implementation must reserve static storage for a
+ * gss_OID_desc object containing the value
+ * {6, (void *)"\x2b\x06\01\x05\x06\x03"},
+ * corresponding to an object identifier value of
+ * {1(iso), 3(org), 6(dod), 1(internet), 5(security),
+ * 6(nametypes), 3(gss-anonymous-name)}.  The constant
+ * and GSS_C_NT_ANONYMOUS should be initialized to point
+ * to that gss_OID_desc.
+ */
+extern const gss_OID_desc * const GSS_C_NT_ANONYMOUS;
+
+
+/*
+ * The implementation must reserve static storage for a
+ * gss_OID_desc object containing the value
+ * {6, (void *)"\x2b\x06\x01\x05\x06\x04"},
+ * corresponding to an object-identifier value of
+ * {1(iso), 3(org), 6(dod), 1(internet), 5(security),
+ * 6(nametypes), 4(gss-api-exported-name)}.  The constant
+ * GSS_C_NT_EXPORT_NAME should be initialized to point
+ * to that gss_OID_desc.
+ */
+extern const gss_OID_desc * const GSS_C_NT_EXPORT_NAME;
+
+
+/* Function Prototypes */
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_acquire_cred
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+            gss_name_t,                        /* desired_name */
+            OM_uint32,                 /* time_req */
+            gss_OID_set,               /* desired_mechs */
+            gss_cred_usage_t,          /* cred_usage */
+            gss_cred_id_t FAR *,       /* output_cred_handle */
+            gss_OID_set FAR *,         /* actual_mechs */
+            OM_uint32 FAR *            /* time_rec */
+           ));
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_release_cred
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+            gss_cred_id_t FAR *                /* cred_handle */
+           ));
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_init_sec_context
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+            gss_cred_id_t,             /* claimant_cred_handle */
+            gss_ctx_id_t FAR *,                /* context_handle */
+            gss_name_t,                        /* target_name */
+            gss_OID,                   /* mech_type (used to be const) */
+            OM_uint32,                 /* req_flags */
+            OM_uint32,                 /* time_req */
+            gss_channel_bindings_t,    /* input_chan_bindings */
+            gss_buffer_t,              /* input_token */
+            gss_OID FAR *,             /* actual_mech_type */
+            gss_buffer_t,              /* output_token */
+            OM_uint32 FAR *,           /* ret_flags */
+            OM_uint32 FAR *            /* time_rec */
+           ));
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_accept_sec_context
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+            gss_ctx_id_t FAR *,                /* context_handle */
+            gss_cred_id_t,             /* acceptor_cred_handle */
+            gss_buffer_t,              /* input_token_buffer */
+            gss_channel_bindings_t,    /* input_chan_bindings */
+            gss_name_t FAR *,          /* src_name */
+            gss_OID FAR *,             /* mech_type */
+            gss_buffer_t,              /* output_token */
+            OM_uint32 FAR *,           /* ret_flags */
+            OM_uint32 FAR *,           /* time_rec */
+            gss_cred_id_t FAR *                /* delegated_cred_handle */
+           ));
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_process_context_token
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+            gss_ctx_id_t,              /* context_handle */
+            gss_buffer_t               /* token_buffer */
+           ));
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_delete_sec_context
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+            gss_ctx_id_t FAR *,                /* context_handle */
+            gss_buffer_t               /* output_token */
+           ));
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_context_time
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+            gss_ctx_id_t,              /* context_handle */
+            OM_uint32 FAR *            /* time_rec */
+           ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_get_mic
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+           gss_ctx_id_t,               /* context_handle */
+           gss_qop_t,                  /* qop_req */
+           gss_buffer_t,               /* message_buffer */
+           gss_buffer_t                /* message_token */
+          ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_verify_mic
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+           gss_ctx_id_t,               /* context_handle */
+           gss_buffer_t,               /* message_buffer */
+           gss_buffer_t,               /* message_token */
+           gss_qop_t *                 /* qop_state */
+          ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_wrap
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+           gss_ctx_id_t,               /* context_handle */
+           int,                        /* conf_req_flag */
+           gss_qop_t,                  /* qop_req */
+           gss_buffer_t,               /* input_message_buffer */
+           int FAR *,                  /* conf_state */
+           gss_buffer_t                /* output_message_buffer */
+          ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_unwrap
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+           gss_ctx_id_t,               /* context_handle */
+           gss_buffer_t,               /* input_message_buffer */
+           gss_buffer_t,               /* output_message_buffer */
+           int FAR *,                  /* conf_state */
+           gss_qop_t FAR *             /* qop_state */
+          ));
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_display_status
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+            OM_uint32,                 /* status_value */
+            int,                       /* status_type */
+            gss_OID,                   /* mech_type (used to be const) */
+            OM_uint32 FAR *,           /* message_context */
+            gss_buffer_t               /* status_string */
+           ));
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_indicate_mechs
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+            gss_OID_set FAR *          /* mech_set */
+           ));
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_compare_name
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+            gss_name_t,                        /* name1 */
+            gss_name_t,                        /* name2 */
+            int FAR *                  /* name_equal */
+           ));
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_display_name
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+            gss_name_t,                        /* input_name */
+            gss_buffer_t,              /* output_name_buffer */
+            gss_OID FAR *              /* output_name_type */
+           ));
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_import_name
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+            gss_buffer_t,              /* input_name_buffer */
+            gss_OID,                   /* input_name_type(used to be const) */
+            gss_name_t FAR *           /* output_name */
+           ));
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_release_name
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+            gss_name_t FAR *           /* input_name */
+           ));
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_release_buffer
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+            gss_buffer_t               /* buffer */
+           ));
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_release_oid_set
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+            gss_OID_set FAR *          /* set */
+           ));
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_inquire_cred
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+            gss_cred_id_t,             /* cred_handle */
+            gss_name_t FAR *,          /* name */
+            OM_uint32 FAR *,           /* lifetime */
+            gss_cred_usage_t FAR *,    /* cred_usage */
+            gss_OID_set FAR *          /* mechanisms */
+           ));
+
+/* Last argument new for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_inquire_context
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+           gss_ctx_id_t,               /* context_handle */
+           gss_name_t FAR *,           /* src_name */
+           gss_name_t FAR *,           /* targ_name */
+           OM_uint32 FAR *,            /* lifetime_rec */
+           gss_OID FAR *,              /* mech_type */
+           OM_uint32 FAR *,            /* ctx_flags */
+           int FAR *,                  /* locally_initiated */
+           int FAR *                   /* open */
+          ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_wrap_size_limit
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+           gss_ctx_id_t,               /* context_handle */
+           int,                        /* conf_req_flag */
+           gss_qop_t,                  /* qop_req */
+           OM_uint32,                  /* req_output_size */
+           OM_uint32 *                 /* max_input_size */
+          ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_import_name_object
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+           void FAR *,                 /* input_name */
+           gss_OID,                    /* input_name_type */
+           gss_name_t FAR *            /* output_name */
+          ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_export_name_object
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+           gss_name_t,                 /* input_name */
+           gss_OID,                    /* desired_name_type */
+           void FAR * FAR *            /* output_name */
+          ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_add_cred
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+           gss_cred_id_t,              /* input_cred_handle */
+           gss_name_t,                 /* desired_name */
+           gss_OID,                    /* desired_mech */
+           gss_cred_usage_t,           /* cred_usage */
+           OM_uint32,                  /* initiator_time_req */
+           OM_uint32,                  /* acceptor_time_req */
+           gss_cred_id_t FAR *,        /* output_cred_handle */
+           gss_OID_set FAR *,          /* actual_mechs */
+           OM_uint32 FAR *,            /* initiator_time_rec */
+           OM_uint32 FAR *             /* acceptor_time_rec */
+          ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_inquire_cred_by_mech
+PROTOTYPE( (OM_uint32  FAR *,          /* minor_status */
+           gss_cred_id_t,              /* cred_handle */
+           gss_OID,                    /* mech_type */
+           gss_name_t FAR *,           /* name */
+           OM_uint32 FAR *,            /* initiator_lifetime */
+           OM_uint32 FAR *,            /* acceptor_lifetime */
+           gss_cred_usage_t FAR *      /* cred_usage */
+          ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_export_sec_context
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+           gss_ctx_id_t FAR *,         /* context_handle */
+           gss_buffer_t                /* interprocess_token */
+           ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_import_sec_context
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+           gss_buffer_t,               /* interprocess_token */
+           gss_ctx_id_t FAR *          /* context_handle */
+           ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_release_oid
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+           gss_OID FAR *               /* oid */
+          ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_create_empty_oid_set
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+           gss_OID_set FAR *           /* oid_set */
+          ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_add_oid_set_member
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+           gss_OID,                    /* member_oid */
+           gss_OID_set FAR *           /* oid_set */
+          ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_test_oid_set_member
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+           gss_OID,                    /* member */
+           gss_OID_set,                /* set */
+           int FAR *                   /* present */
+          ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_str_to_oid
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+           gss_buffer_t,               /* oid_str */
+           gss_OID FAR *               /* oid */
+          ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_oid_to_str
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+           gss_OID,                    /* oid */
+           gss_buffer_t                /* oid_str */
+          ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_inquire_names_for_mech
+PROTOTYPE( (OM_uint32 FAR *,           /* minor_status */
+           gss_OID,                    /* mechanism */
+           gss_OID_set FAR *           /* name_types */
+          ));
+
+/*
+ * The following routines are obsolete variants of gss_get_mic, gss_wrap,
+ * gss_verify_mic and gss_unwrap.  They should be provided by GSSAPI V2
+ * implementations for backwards compatibility with V1 applications.  Distinct
+ * entrypoints (as opposed to #defines) should be provided, to allow GSSAPI
+ * V1 applications to link against GSSAPI V2 implementations.
+ */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_sign
+PROTOTYPE( (OM_uint32 FAR *,    /* minor_status */
+            gss_ctx_id_t,      /* context_handle */
+            int,               /* qop_req */
+            gss_buffer_t,      /* message_buffer */
+            gss_buffer_t       /* message_token */
+           ));
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_verify
+PROTOTYPE( (OM_uint32 FAR *,    /* minor_status */
+            gss_ctx_id_t,      /* context_handle */
+            gss_buffer_t,      /* message_buffer */
+            gss_buffer_t,      /* token_buffer */
+            int FAR *           /* qop_state */
+           ));
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_seal
+PROTOTYPE( (OM_uint32 FAR *,    /* minor_status */
+            gss_ctx_id_t,      /* context_handle */
+            int,               /* conf_req_flag */
+            int,               /* qop_req */
+            gss_buffer_t,      /* input_message_buffer */
+            int FAR *,          /* conf_state */
+            gss_buffer_t       /* output_message_buffer */
+           ));
+
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_unseal
+PROTOTYPE( (OM_uint32 FAR *,    /* minor_status */
+            gss_ctx_id_t,      /* context_handle */
+            gss_buffer_t,      /* input_message_buffer */
+            gss_buffer_t,      /* output_message_buffer */
+            int FAR *,          /* conf_state */
+            int FAR *           /* qop_state */
+           ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_export_name
+PROTOTYPE(     (OM_uint32  *,          /* minor_status */
+                const gss_name_t,      /* input_name */
+                gss_buffer_t           /* exported_name */
+       ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_duplicate_name
+PROTOTYPE(     (OM_uint32  *,          /* minor_status */
+                const gss_name_t,      /* input_name */
+                gss_name_t *           /* dest_name */
+       ));
+
+/* New for V2 */
+GSS_DLLIMP OM_uint32 KRB5_CALLCONV gss_canonicalize_name
+PROTOTYPE(     (OM_uint32  *,          /* minor_status */
+                const gss_name_t,      /* input_name */
+                const gss_OID,         /* mech_type */
+                gss_name_t *           /* output_name */
+       ));
+
+#if TARGET_OS_MAC
+    #if defined(__MWERKS__)
+        #pragma enumsalwaysint reset
+        #pragma import reset
+    #endif
+       #pragma options align=reset
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+/* XXXX these are not part of the GSSAPI C bindings!  (but should be) */
+
+#define GSS_CALLING_ERROR_FIELD(x) \
+   (((x) >> GSS_C_CALLING_ERROR_OFFSET) & GSS_C_CALLING_ERROR_MASK)
+#define GSS_ROUTINE_ERROR_FIELD(x) \
+   (((x) >> GSS_C_ROUTINE_ERROR_OFFSET) & GSS_C_ROUTINE_ERROR_MASK)
+#define GSS_SUPPLEMENTARY_INFO_FIELD(x) \
+   (((x) >> GSS_C_SUPPLEMENTARY_OFFSET) & GSS_C_SUPPLEMENTARY_MASK)
+
+/* XXXX This is a necessary evil until the spec is fixed */
+#define GSS_S_CRED_UNAVAIL GSS_S_FAILURE
+
+#endif /* _GSSAPI_H_ */
index 2eeb93b..58c84f8 100644 (file)
@@ -1,7 +1,7 @@
 
 include        $(TOP)rules.mk
 
-LIBS   = libnfs.a libexport.a libmisc.a
+LIBS   = libnfs.a libexport.a libmisc.a librpc.a libgssapi.a
 
 all install::  $(LIBS)
        @:
diff --git a/support/rpc/DISCLAIMER b/support/rpc/DISCLAIMER
new file mode 100644 (file)
index 0000000..e5871a2
--- /dev/null
@@ -0,0 +1,30 @@
+/*     $OpenBSD: DISCLAIMER,v 1.2 1996/07/20 06:12:14 deraadt Exp $    */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part.  Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California  94043
+ */
diff --git a/support/rpc/Makefile b/support/rpc/Makefile
new file mode 100644 (file)
index 0000000..d678075
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# librpc.a
+# rpc library with rpcsec_gss
+#
+
+LIBNAME        = librpc.a
+SRCS   = auth_gss.c authgss_prot.c svc.c svc_run.c svc_auth.c \
+         svc_auth_none.c svc_auth_unix.c svc_auth_gss.c \
+         svc_raw.c svc_simple.c svc_tcp.c svc_udp.c \
+         rpc_commondata.c
+OBJS   = $(SRCS:.c=.o)
+
+include $(TOP)rules.mk
+
+CFLAGS += -I$(TOP)support/rpc/include -DDEBUG
+
+install::
+       @:
diff --git a/support/rpc/README b/support/rpc/README
new file mode 100644 (file)
index 0000000..eb960e6
--- /dev/null
@@ -0,0 +1,233 @@
+RPCSRC 4.0 7/11/89
+
+This distribution contains Sun Microsystem's implementation of the
+RPC and XDR protocols and is compatible with 4.2BSD and 4.3BSD.  Also
+included is complete documentation, utilities, RPC service
+specification files, and demonstration services in the format used by
+the RPC protocol compiler (rpcgen).  See WHAT'S NEW below for
+details.
+
+NOTE ABOUT SECURE RPC:
+
+This release of RPCSRC contains most of the code needed to implement
+Secure RPC (see "DES Authentication" in the RPC Protocol Specification,
+doc/rpc.rfc.ms).  Due to legal considerations, we are unable to
+distribute an implementation of DES, the Data Encryption Standard, which
+Secure RPC requires.  For this reason, all of the files, documentation, and
+programs associated with Secure RPC have been placed into a separate
+directory, secure_rpc.  The RPC library contained in the main body of this
+release *DOES NOT* support Secure RPC.  See secure_rpc/README for more
+details.  (A DES library was posted in Volume 18 of comp.sources.unix.)
+
+If you wish to report bugs found in this release, send mail to:
+
+Portable ONC/NFS
+Sun Microsystems, Inc
+MS 12-33
+2550 Garcia Avenue
+Mountain View, CA  94043
+
+or send Email to nfsnet@sun.com (the Internet) or sun!nfsnet (Usenet).
+
+ROADMAP
+
+The directory hierarchy is as follows:
+
+    demo/       Various demonstration services
+    demo/dir        Remote directory lister
+    demo/msg        Remote console message delivery service
+    demo/sort       Remote sort service
+
+    doc/        Documentation for RPC, XDR and NFS in "-ms" format.
+
+    etc/        Utilities (rpcinfo and portmap).  portmap must be
+                started by root before any other RPC network services are
+                used.  SEE BELOW FOR BUGFIX TO 4.3BSD COMPILER.
+
+    man/        Manual pages for RPC library, rpcgen, and utilities.
+
+    rpc/        The RPC and XDR library.  SEE BELOW
+                FOR BUGFIX TO 4.2BSD COMPILER.
+
+    rpcgen/     The RPC Language compiler (for .x files)
+
+    rpcsvc/     Service definition files for various services and the
+                server and client code for the Remote Status service.
+
+    secure_rpc/ The files in this directory are used to build a version of
+                the RPC library with DES Authentication.  See the README
+                file in that directory for more details.
+
+BUILD INSTRUCTIONS
+
+Makefiles can be found in all directories except for man.  The
+Makefile in the top directory will cause these others to be invoked
+(except for in the doc, man and demo directories), in turn building the
+entire release.
+
+WARNING!  THE DEFAULT INSTALLATION PROCEDURES WILL INSTALL FILES
+IN /usr/include, /usr/lib, /usr/bin and /etc.
+
+The master RPC include file, rpc/rpc.h, is used by all programs and
+routines that use RPC.  It includes other RPC and system include files
+needed by the RPC system.  PLEASE NOTE: If your system has NFS, it
+may have been based on Sun's NFS Source.  The include files installed
+by this package may duplicate include files you will find on your NFS
+system.  The RPCSRC 4.0 include files are upwardly compatible to all
+NFS Source include files as of the date of this distribution (not
+including any new definitions or declarations added by your system
+vendor).  HOWEVER: Please read the comments towards the end of
+rpc/rpc.h regarding rpc/netdb.h.  You may need to uncomment the
+inclusion of that file if the structures it defines are already
+defined by your system's include files.
+
+After making any compiler fixes that are needed (see below), at
+the top directory, type:
+
+    make install
+
+For all installations, the Makefile macro DESTDIR is prepended to the
+installation path.  It is defined to be null in the Makefiles, so
+installations are relative to root.  (You will probably need root
+privileges for installing the files under the default path.)  To
+install the files under some other tree (e.g., /usr/local), use the
+command:
+
+    make install DESTDIR=/usr/local
+
+This will place the include files in /usr/local/usr/include, the RPC
+library in /usr/local/usr/lib, rpcgen in /usr/local/usr/bin, and the
+utilities in /usr/local/etc.  You'll have to edit the Makefiles or
+install the files by hand if you want to do anything other than this
+kind of relocation of the installation tree.
+
+The RPC library will be built and installed first.  By default it is
+installed in /usr/lib as "librpclib.a".  The directory
+/usr/include/rpc will also be created, and several header files will
+be installed there.  ALL RPC SERVICES INCLUDE THESE HEADER FILES.
+
+The programs in etc/ link in routines from librpclib.a.  If you change
+where it is installed, be sure to edit etc/'s Makefile to reflect this.
+These programs are installed in /etc.  PORTMAP MUST BE RUNNING ON
+YOUR SYSTEM BEFORE YOU START ANY OTHER RPC SERVICE.
+
+rpcgen is installed in /usr/bin.  This program is required to build
+the demonstration services in demo and the rstat client and server in
+rpcsvc/.
+
+The rpcsvc/ directory will install its files in the directory
+/usr/include/rpcsvc.  The Remote Status service (rstat_svc) will be
+compiled and installed in /etc.  If you wish to make this service
+available, you should either start this service when needed or have
+it started at boot time by invoking it in your /etc/rc.local script.
+(Be sure that portmap is started first!)  Sun has modified its
+version of inetd to automatically start RPC services.  (Use "make
+LIB=" when building rstat on a Sun Workstation.)  The Remote Status
+client (rstat) will be installed in /usr/bin.  This program queries
+the rstat_svc on a remote host and prints a system status summary
+similar to the one printed by "uptime".
+
+The documentation is not built during the "make install" command.
+Typing "make" in the doc directory will cause all of the manuals to
+be formatted using nroff into a single file.  We have had a report
+that certain "troff" equivalents have trouble processing the full
+manual.  If you have trouble, try building the manuals individually
+(see the Makefile).
+
+The demonstration services in the demo directory are not built by the
+top-level "make install" command.  To build these, cd to the demo
+directory and enter "make".  The three services will be built.
+RPCGEN MUST BE INSTALLED in a path that make can find.  To run the
+services, start the portmap program as root and invoke the service
+(you probably will want to put it in the background).  rpcinfo can be
+used to check that the service succeeded in getting registered with
+portmap, and to ping the service (see rpcinfo's man page).  You can
+then use the corresponding client program to exercise the service.
+To build these services on a Sun workstation, you must prevent the
+Makefile from trying to link the RPC library (as these routines are
+already a part of Sun's libc).  Use: "make LIB=".
+
+BUGFIX FOR 4.3BSD COMPILER
+
+The use of a 'void *' declaration for one of the arguments in
+the reply_proc() procedure in etc/rpcinfo.c will trigger a bug
+in the 4.3BSD compiler.  The bug is fixed by the following change to
+the compiler file mip/manifest.h:
+
+*** manifest.h.r1.1    Thu Apr 30 13:52:25 1987
+--- manifest.h.r1.2    Mon Nov 23 18:58:17 1987
+***************
+*** 21,27 ****
+  /*
+   * Bogus type values
+   */
+! #define TNULL        PTR             /* pointer to UNDEF */
+  #define TVOID        FTN             /* function returning UNDEF (for void) */
+
+  /*
+--- 21,27 ----
+  /*
+   * Bogus type values
+   */
+! #define TNULL        INCREF(MOETY)   /* pointer to MOETY -- impossible type */
+  #define TVOID        FTN             /* function returning UNDEF (for void) */
+
+  /*
+
+If you cannot fix your compiler, change the declaration in reply_proc()
+from 'void *' to 'char *'.
+
+BUGFIX FOR 4.2BSD COMPILER
+
+Unpatched 4.2BSD compilers complain about valid C.  You can make old
+compilers happy by changing some voids to ints.  However, the fix to
+the 4.2 VAX compiler is as follows (to mip/trees.c):
+
+*** trees.c.r1.1       Mon May 11 13:47:58 1987
+--- trees.c.r1.2       Wed Jul  2 18:28:52 1986
+***************
+*** 1247,1253 ****
+               if(o==CAST && mt1==0)return(TYPL+TYMATCH);
+               if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
+               else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
+!              else if( mt12 == 0 ) break;
+               else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
+               else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
+               break;
+--- 1261,1269 ----
+               if(o==CAST && mt1==0)return(TYPL+TYMATCH);
+               if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
+               else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
+!              /* if right is TVOID and looks like a CALL, is not ok */
+!              else if (mt2 == 0 && (p->in.right->in.op == CALL || p->in.right->in.op == UNARY CALL))
+!                      break;
+               else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
+               else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
+               break;
+
+WHAT'S NEW IN THIS RELEASE: RPCSRC 4.0
+
+The previous release was RPCSRC 3.9.  As with all previous releases,
+this release is based directly on files from Sun Microsystem's
+implementation.
+
+Upgrade from RPCSRC 3.9
+
+1)  RPCSRC 4.0 upgrades RPCSRC 3.9.  Improvements from SunOS 4.0 have
+    been integrated into this release.
+
+Secure RPC (in the secure_rpc/ directory)
+
+2)  DES Authentication routines and programs are provided.
+3)  A new manual, "Secure NFS" is provided, which describes Secure RPC
+    and Secure NFS.
+4)  Skeleton routines and manual pages are provided which describe the
+    DES encryption procedures required by Secure RPC.  HOWEVER, NO DES
+    ROUTINE IS PROVIDED.
+
+New Functionality
+
+5)  rpcinfo can now be used to de-register services from the portmapper
+    which may have terminated abnormally.
+6)  A new client, rstat, is provided which queries the rstat_svc and
+    prints a status line similar to the one displayed by "uptime".
diff --git a/support/rpc/auth_gss.c b/support/rpc/auth_gss.c
new file mode 100644 (file)
index 0000000..f41d678
--- /dev/null
@@ -0,0 +1,628 @@
+/*
+  auth_gss.c
+
+  RPCSEC_GSS client routines.
+
+  Copyright (c) 2000 The Regents of the University of Michigan.
+  All rights reserved.
+
+  Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
+  All rights reserved, all wrongs reversed.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+  3. Neither the name of the University nor the names of its
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_gss.h>
+#include <rpc/clnt.h>
+#include <netinet/in.h>
+#include <gssapi/gssapi.h>
+
+static void    authgss_nextverf();
+static bool_t  authgss_marshal();
+static bool_t  authgss_refresh();
+static bool_t  authgss_validate();
+static void    authgss_destroy();
+static void    authgss_destroy_context();
+static bool_t  authgss_wrap();
+static bool_t  authgss_unwrap();
+
+
+/*
+ * 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 struct auth_ops authgss_ops = {
+       authgss_nextverf,
+       authgss_marshal,
+       authgss_validate,
+       authgss_refresh,
+       authgss_destroy,
+       authgss_wrap,
+       authgss_unwrap
+};
+
+#ifdef DEBUG
+
+/* useful as i add more mechanisms */
+void
+print_rpc_gss_sec(struct rpc_gss_sec *ptr)
+{
+int i;
+char *p;
+
+       log_debug("rpc_gss_sec:");
+       if(ptr->mech == NULL)
+               log_debug("NULL gss_OID mech");
+       else {
+               fprintf(stderr, "     mechanism_OID: {");
+               p = (char *)ptr->mech->elements;
+               for (i=0; i < ptr->mech->length; i++)
+                       /* First byte of OIDs encoded to save a byte */
+                       if (i == 0) {
+                               int first, second;
+                               if (*p < 40) {
+                                       first = 0;
+                                       second = *p;
+                               }
+                               else if (40 <= *p && *p < 80) {
+                                       first = 1;
+                                       second = *p - 40;
+                               }
+                               else if (80 <= *p && *p < 127) {
+                                       first = 2;
+                                       second = *p - 80;
+                               }
+                               else {
+                                       /* Invalid value! */
+                                       first = -1;
+                                       second = -1;
+                               }
+                               fprintf(stderr, " %u %u", first, second);
+                               p++;
+                       }
+                       else {
+                               fprintf(stderr, " %u", (unsigned char)*p++);
+                       }
+               fprintf(stderr, " }\n");
+       }
+       fprintf(stderr, "     qop: %d\n", ptr->qop);
+       fprintf(stderr, "     service: %d\n", ptr->svc);
+       fprintf(stderr, "     cred: %p\n", ptr->cred);
+}
+#endif /*DEBUG*/
+
+struct rpc_gss_data {
+       bool_t                   established;   /* context established */
+       gss_buffer_desc          gc_wire_verf;  /* save GSS_S_COMPLETE NULL RPC verfier
+                                                * to process at end of context negotiation*/
+       CLIENT                  *clnt;          /* client handle */
+       gss_name_t               name;          /* service name */
+       struct rpc_gss_sec       sec;           /* security tuple */
+       gss_ctx_id_t             ctx;           /* context id */
+       struct rpc_gss_cred      gc;            /* client credentials */
+       u_int                    win;           /* sequence window */
+};
+
+#define        AUTH_PRIVATE(auth)      ((struct rpc_gss_data *)auth->ah_private)
+
+static struct timeval AUTH_TIMEOUT = { 25, 0 };
+
+AUTH *
+authgss_create(CLIENT *clnt, gss_name_t name, struct rpc_gss_sec *sec)
+{
+       AUTH                    *auth, *save_auth;
+       struct rpc_gss_data     *gd;
+       OM_uint32               min_stat = 0;
+
+       log_debug("in authgss_create()");
+
+       memset(&rpc_createerr, 0, sizeof(rpc_createerr));
+
+       if ((auth = calloc(sizeof(*auth), 1)) == NULL) {
+               rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+               rpc_createerr.cf_error.re_errno = ENOMEM;
+               return (NULL);
+       }
+       if ((gd = calloc(sizeof(*gd), 1)) == NULL) {
+               rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+               rpc_createerr.cf_error.re_errno = ENOMEM;
+               free(auth);
+               return (NULL);
+       }
+#ifdef DEBUG
+       fprintf(stderr, "authgss_create: name is %p\n", name);
+#endif
+       if (name != GSS_C_NO_NAME) {
+               if (gss_duplicate_name(&min_stat, name, &gd->name)
+                                               != GSS_S_COMPLETE) {
+                       rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+                       rpc_createerr.cf_error.re_errno = ENOMEM;
+                       free(auth);
+                       return (NULL);
+               }
+       }
+       else
+               gd->name = name;
+
+#ifdef DEBUG
+       fprintf(stderr, "authgss_create: gd->name is %p\n", gd->name);
+#endif
+       gd->clnt = clnt;
+       gd->ctx = GSS_C_NO_CONTEXT;
+       gd->sec = *sec;
+
+       gd->gc.gc_v = RPCSEC_GSS_VERSION;
+       gd->gc.gc_proc = RPCSEC_GSS_INIT;
+       gd->gc.gc_svc = gd->sec.svc;
+
+       auth->ah_ops = &authgss_ops;
+       auth->ah_private = (caddr_t)gd;
+
+       save_auth = clnt->cl_auth;
+       clnt->cl_auth = auth;
+
+       if (!authgss_refresh(auth))
+               auth = NULL;
+
+       clnt->cl_auth = save_auth;
+
+       return (auth);
+}
+
+AUTH *
+authgss_create_default(CLIENT *clnt, char *service, struct rpc_gss_sec *sec)
+{
+       AUTH                    *auth;
+       OM_uint32                maj_stat = 0, min_stat = 0;
+       gss_buffer_desc          sname;
+       gss_name_t               name = GSS_C_NO_NAME;
+
+       log_debug("in authgss_create_default()");
+
+
+       sname.value = service;
+       sname.length = strlen(service);
+
+       maj_stat = gss_import_name(&min_stat, &sname,
+               GSS_C_NT_HOSTBASED_SERVICE,
+               &name);
+
+       if (maj_stat != GSS_S_COMPLETE) {
+               log_status("gss_import_name", maj_stat, min_stat);
+               rpc_createerr.cf_stat = RPC_AUTHERROR;
+               return (NULL);
+       }
+
+       auth = authgss_create(clnt, name, sec);
+
+       if (name != GSS_C_NO_NAME) {
+#ifdef DEBUG
+       fprintf(stderr, "authgss_create_default: freeing name %p\n", name);
+#endif
+               gss_release_name(&min_stat, &name);
+       }
+
+       return (auth);
+}
+
+bool_t
+authgss_get_private_data(AUTH *auth, struct authgss_private_data *pd)
+{
+       struct rpc_gss_data     *gd;
+
+       log_debug("in authgss_get_private_data()");
+
+       if (!auth || !pd)
+               return (FALSE);
+
+       gd = AUTH_PRIVATE(auth);
+
+       if (!gd || !gd->established)
+               return (FALSE);
+
+       pd->pd_ctx = gd->ctx;
+       pd->pd_ctx_hndl = gd->gc.gc_ctx;
+       pd->pd_seq_win = gd->win;
+
+       return (TRUE);
+}
+
+static void
+authgss_nextverf(AUTH *auth)
+{
+       log_debug("in authgss_nextverf()");
+       /* no action necessary */
+}
+
+static bool_t
+authgss_marshal(AUTH *auth, XDR *xdrs)
+{
+       XDR                      tmpxdrs;
+       char                     tmp[MAX_AUTH_BYTES];
+       struct rpc_gss_data     *gd;
+       gss_buffer_desc          rpcbuf, checksum;
+       OM_uint32                maj_stat, min_stat;
+       bool_t                   xdr_stat;
+
+       log_debug("in authgss_marshal()");
+
+       gd = AUTH_PRIVATE(auth);
+
+       if (gd->established)
+               gd->gc.gc_seq++;
+
+       xdrmem_create(&tmpxdrs, tmp, sizeof(tmp), XDR_ENCODE);
+
+       if (!xdr_rpc_gss_cred(&tmpxdrs, &gd->gc)) {
+               XDR_DESTROY(&tmpxdrs);
+               return (FALSE);
+       }
+       auth->ah_cred.oa_flavor = RPCSEC_GSS;
+       auth->ah_cred.oa_base = tmp;
+       auth->ah_cred.oa_length = XDR_GETPOS(&tmpxdrs);
+
+       XDR_DESTROY(&tmpxdrs);
+
+       if (!xdr_opaque_auth(xdrs, &auth->ah_cred))
+               return (FALSE);
+
+       if (gd->gc.gc_proc == RPCSEC_GSS_INIT ||
+           gd->gc.gc_proc == RPCSEC_GSS_CONTINUE_INIT) {
+               return (xdr_opaque_auth(xdrs, &_null_auth));
+       }
+       /* Checksum serialized RPC header, up to and including credential. */
+       rpcbuf.length = XDR_GETPOS(xdrs);
+       XDR_SETPOS(xdrs, 0);
+       rpcbuf.value = XDR_INLINE(xdrs, rpcbuf.length);
+
+       maj_stat = gss_get_mic(&min_stat, gd->ctx, gd->sec.qop,
+                           &rpcbuf, &checksum);
+
+       if (maj_stat != GSS_S_COMPLETE) {
+               log_status("gss_get_mic", maj_stat, min_stat);
+               if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
+                       gd->established = FALSE;
+                       authgss_destroy_context(auth);
+               }
+               return (FALSE);
+       }
+       auth->ah_verf.oa_flavor = RPCSEC_GSS;
+       auth->ah_verf.oa_base = checksum.value;
+       auth->ah_verf.oa_length = checksum.length;
+
+       xdr_stat = xdr_opaque_auth(xdrs, &auth->ah_verf);
+       gss_release_buffer(&min_stat, &checksum);
+
+       return (xdr_stat);
+}
+
+static bool_t
+authgss_validate(AUTH *auth, struct opaque_auth *verf)
+{
+       struct rpc_gss_data     *gd;
+       u_int                    num, qop_state;
+       gss_buffer_desc          signbuf, checksum;
+       OM_uint32                maj_stat, min_stat;
+
+       log_debug("in authgss_validate()");
+
+       gd = AUTH_PRIVATE(auth);
+
+       if (gd->established == FALSE) {
+               /* would like to do this only on NULL rpc --
+                * gc->established is good enough.
+                * save the on the wire verifier to validate last
+                * INIT phase packet after decode if the major
+                * status is GSS_S_COMPLETE
+                */
+               if ((gd->gc_wire_verf.value =
+                               mem_alloc(verf->oa_length)) == NULL) {
+                       fprintf(stderr, "gss_validate: out of memory\n");
+                       return (FALSE);
+               }
+               memcpy(gd->gc_wire_verf.value, verf->oa_base, verf->oa_length);
+               gd->gc_wire_verf.length = verf->oa_length;
+               return (TRUE);
+       }
+
+       if (gd->gc.gc_proc == RPCSEC_GSS_INIT ||
+           gd->gc.gc_proc == RPCSEC_GSS_CONTINUE_INIT) {
+               num = htonl(gd->win);
+       }
+       else num = htonl(gd->gc.gc_seq);
+
+       signbuf.value = &num;
+       signbuf.length = sizeof(num);
+
+       checksum.value = verf->oa_base;
+       checksum.length = verf->oa_length;
+
+       maj_stat = gss_verify_mic(&min_stat, gd->ctx, &signbuf,
+                                 &checksum, &qop_state);
+       if (maj_stat != GSS_S_COMPLETE || qop_state != gd->sec.qop) {
+               log_status("gss_verify_mic", maj_stat, min_stat);
+               if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
+                       gd->established = FALSE;
+                       authgss_destroy_context(auth);
+               }
+               return (FALSE);
+       }
+       return (TRUE);
+}
+
+static bool_t
+authgss_refresh(AUTH *auth)
+{
+       struct rpc_gss_data     *gd;
+       struct rpc_gss_init_res  gr;
+       gss_buffer_desc         *recv_tokenp, send_token;
+       OM_uint32                maj_stat, min_stat, call_stat, ret_flags;
+       OM_uint32                req_flags=0;
+
+       log_debug("in authgss_refresh()");
+
+       gd = AUTH_PRIVATE(auth);
+
+       if (gd->established)
+               return (TRUE);
+
+       /* GSS context establishment loop. */
+       memset(&gr, 0, sizeof(gr));
+       recv_tokenp = GSS_C_NO_BUFFER;
+
+#ifdef DEBUG
+       print_rpc_gss_sec(&gd->sec);
+#endif /*DEBUG*/
+
+       for (;;) {
+#ifdef DEBUG
+               /* print the token we just received */
+               if (recv_tokenp != GSS_C_NO_BUFFER) {
+                       log_debug("The token we just received (length %d):",
+                                 recv_tokenp->length);
+                       log_hexdump(recv_tokenp->value, recv_tokenp->length, 0);
+               }
+#endif
+               maj_stat = gss_init_sec_context(&min_stat,
+                                               gd->sec.cred,
+                                               &gd->ctx,
+                                               gd->name,
+                                               gd->sec.mech,
+                                               gd->sec.req_flags,
+                                               0,              /* time req */
+                                               NULL,           /* channel */
+                                               recv_tokenp,
+                                               NULL,           /* used mech */
+                                               &send_token,
+                                               &ret_flags,
+                                               NULL);          /* time rec */
+
+               if (recv_tokenp != GSS_C_NO_BUFFER) {
+                       gss_release_buffer(&min_stat, &gr.gr_token);
+                       recv_tokenp = GSS_C_NO_BUFFER;
+               }
+               if (maj_stat != GSS_S_COMPLETE &&
+                   maj_stat != GSS_S_CONTINUE_NEEDED) {
+                       log_status("gss_init_sec_context", maj_stat, min_stat);
+                       break;
+               }
+               if (send_token.length != 0) {
+                       memset(&gr, 0, sizeof(gr));
+
+#ifdef DEBUG
+                       /* print the token we are about to send */
+                       log_debug("The token being sent (length %d):",
+                                 send_token.length);
+                       log_hexdump(send_token.value, send_token.length, 0);
+#endif
+
+                       call_stat = clnt_call(gd->clnt, NULLPROC,
+                                             xdr_rpc_gss_init_args,
+                                             &send_token,
+                                             xdr_rpc_gss_init_res,
+                                             (caddr_t)&gr, AUTH_TIMEOUT);
+
+                       gss_release_buffer(&min_stat, &send_token);
+
+                       if (call_stat != RPC_SUCCESS ||
+                           (gr.gr_major != GSS_S_COMPLETE &&
+                            gr.gr_major != GSS_S_CONTINUE_NEEDED))
+                               return FALSE;
+
+                       if (gr.gr_ctx.length != 0) {
+                               if (gd->gc.gc_ctx.value)
+                                       gss_release_buffer(&min_stat,
+                                                          &gd->gc.gc_ctx);
+                               gd->gc.gc_ctx = gr.gr_ctx;
+                       }
+                       if (gr.gr_token.length != 0) {
+                               if (maj_stat != GSS_S_CONTINUE_NEEDED)
+                                       break;
+                               recv_tokenp = &gr.gr_token;
+                       }
+                       gd->gc.gc_proc = RPCSEC_GSS_CONTINUE_INIT;
+               }
+
+               /* GSS_S_COMPLETE => check gss header verifier,
+                * usually checked in gss_validate
+                */
+               if (maj_stat == GSS_S_COMPLETE) {
+                       gss_buffer_desc   bufin;
+                       gss_buffer_desc   bufout;
+                       u_int seq, qop_state = 0;
+
+                       seq = htonl(gr.gr_win);
+                       bufin.value = (unsigned char *)&seq;
+                       bufin.length = sizeof(seq);
+                       bufout.value = (unsigned char *)gd->gc_wire_verf.value;
+                       bufout.length = gd->gc_wire_verf.length;
+
+                       maj_stat = gss_verify_mic(&min_stat, gd->ctx,
+                               &bufin, &bufout, &qop_state);
+
+                       if (maj_stat != GSS_S_COMPLETE
+                                       || qop_state != gd->sec.qop) {
+                               log_status("gss_verify_mic", maj_stat, min_stat);
+                               if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
+                                       gd->established = FALSE;
+                                       authgss_destroy_context(auth);
+                               }
+                               return (FALSE);
+                       }
+                       gd->established = TRUE;
+                       gd->gc.gc_proc = RPCSEC_GSS_DATA;
+                       gd->gc.gc_seq = 0;
+                       gd->win = gr.gr_win;
+                       break;
+               }
+       }
+       /* End context negotiation loop. */
+       if (gd->gc.gc_proc != RPCSEC_GSS_DATA) {
+               if (gr.gr_token.length != 0)
+                       gss_release_buffer(&min_stat, &gr.gr_token);
+
+               authgss_destroy(auth);
+               auth = NULL;
+               rpc_createerr.cf_stat = RPC_AUTHERROR;
+
+               return (FALSE);
+       }
+       return (TRUE);
+}
+
+bool_t
+authgss_service(AUTH *auth, int svc)
+{
+       struct rpc_gss_data     *gd;
+
+       log_debug("in authgss_service()");
+
+       if (!auth)
+               return(FALSE);
+       gd = AUTH_PRIVATE(auth);
+       if (!gd || !gd->established)
+               return (FALSE);
+       gd->sec.svc = svc;
+       gd->gc.gc_svc = svc;
+       return (TRUE);
+}
+
+static void
+authgss_destroy_context(AUTH *auth)
+{
+       struct rpc_gss_data     *gd;
+       OM_uint32                min_stat;
+
+       log_debug("in authgss_destroy_context()");
+
+       gd = AUTH_PRIVATE(auth);
+
+       if (gd->gc.gc_ctx.length != 0) {
+               if (gd->established) {
+                       gd->gc.gc_proc = RPCSEC_GSS_DESTROY;
+                       clnt_call(gd->clnt, NULLPROC, xdr_void, NULL,
+                                 xdr_void, NULL, AUTH_TIMEOUT);
+               }
+               gss_release_buffer(&min_stat, &gd->gc.gc_ctx);
+               /* XXX ANDROS check size of context  - should be 8 */
+               memset(&gd->gc.gc_ctx, 0, sizeof(gd->gc.gc_ctx));
+       }
+       if (gd->ctx != GSS_C_NO_CONTEXT) {
+               gss_delete_sec_context(&min_stat, &gd->ctx, NULL);
+               gd->ctx = GSS_C_NO_CONTEXT;
+       }
+       gd->established = FALSE;
+}
+
+static void
+authgss_destroy(AUTH *auth)
+{
+       struct rpc_gss_data     *gd;
+       OM_uint32                min_stat;
+
+       log_debug("in authgss_destroy()");
+
+       gd = AUTH_PRIVATE(auth);
+
+       authgss_destroy_context(auth);
+
+#ifdef DEBUG
+       fprintf(stderr, "authgss_destroy: freeing name %p\n", gd->name);
+#endif
+       if (gd->name != GSS_C_NO_NAME)
+               gss_release_name(&min_stat, &gd->name);
+
+       free(gd);
+       free(auth);
+}
+
+bool_t
+authgss_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
+{
+       struct rpc_gss_data     *gd;
+
+       log_debug("in authgss_wrap()");
+
+       gd = AUTH_PRIVATE(auth);
+
+       if (!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) {
+               return ((*xdr_func)(xdrs, xdr_ptr));
+       }
+       return (xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr,
+                                gd->ctx, gd->sec.qop,
+                                gd->sec.svc, gd->gc.gc_seq));
+}
+
+bool_t
+authgss_unwrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
+{
+       struct rpc_gss_data     *gd;
+
+       log_debug("in authgss_unwrap()");
+
+       gd = AUTH_PRIVATE(auth);
+
+       if (!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) {
+               return ((*xdr_func)(xdrs, xdr_ptr));
+       }
+       return (xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr,
+                                gd->ctx, gd->sec.qop,
+                                gd->sec.svc, gd->gc.gc_seq));
+}
diff --git a/support/rpc/authgss_prot.c b/support/rpc/authgss_prot.c
new file mode 100644 (file)
index 0000000..97724f1
--- /dev/null
@@ -0,0 +1,355 @@
+/*
+  authgss_prot.c
+
+  Copyright (c) 2000 The Regents of the University of Michigan.
+  All rights reserved.
+
+  Copyright (c) 2000 Dug Song <dugsong@UMICH.EDU>.
+  All rights reserved, all wrongs reversed.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions
+  are met:
+
+  1. Redistributions of source code must retain the above copyright
+     notice, this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in the
+     documentation and/or other materials provided with the distribution.
+  3. Neither the name of the University nor the names of its
+     contributors may be used to endorse or promote products derived
+     from this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_gss.h>
+#include <rpc/rpc.h>
+#include <gssapi/gssapi.h>
+
+bool_t
+xdr_rpc_gss_cred(XDR *xdrs, struct rpc_gss_cred *p)
+{
+       bool_t xdr_stat;
+
+       xdr_stat = (xdr_u_int(xdrs, &p->gc_v) &&
+                   xdr_enum(xdrs, (enum_t *)&p->gc_proc) &&
+                   xdr_u_int(xdrs, &p->gc_seq) &&
+                   xdr_enum(xdrs, (enum_t *)&p->gc_svc) &&
+                   xdr_bytes(xdrs, (char **)&p->gc_ctx.value,
+                             &p->gc_ctx.length, MAX_AUTH_BYTES));
+
+       log_debug("xdr_rpc_gss_cred: %s %s "
+                 "(v %d, proc %d, seq %d, svc %d, ctx %p:%d)",
+                 (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
+                 (xdr_stat == TRUE) ? "success" : "failure",
+                 p->gc_v, p->gc_proc, p->gc_seq, p->gc_svc,
+                 p->gc_ctx.value, p->gc_ctx.length);
+
+       return (xdr_stat);
+}
+
+bool_t
+xdr_rpc_gss_init_args(XDR *xdrs, gss_buffer_desc *p)
+{
+       bool_t xdr_stat;
+
+       xdr_stat = xdr_bytes(xdrs, (char **)&p->value,
+                             &p->length, MAX_NETOBJ_SZ);
+
+       log_debug("xdr_rpc_gss_init_args: %s %s (token %p:%d)",
+                 (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
+                 (xdr_stat == TRUE) ? "success" : "failure",
+                 p->value, p->length);
+
+       return (xdr_stat);
+}
+
+bool_t
+xdr_rpc_gss_init_res(XDR *xdrs, struct rpc_gss_init_res *p)
+{
+       bool_t xdr_stat;
+
+       xdr_stat = (xdr_bytes(xdrs, (char **)&p->gr_ctx.value,
+                             &p->gr_ctx.length, MAX_NETOBJ_SZ) &&
+                   xdr_u_int(xdrs, &p->gr_major) &&
+                   xdr_u_int(xdrs, &p->gr_minor) &&
+                   xdr_u_int(xdrs, &p->gr_win) &&
+                   xdr_bytes(xdrs, (char **)&p->gr_token.value,
+                             &p->gr_token.length, MAX_NETOBJ_SZ));
+
+       log_debug("xdr_rpc_gss_init_res %s %s "
+                 "(ctx %p:%d, maj %d, min %d, win %d, token %p:%d)",
+                 (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode",
+                 (xdr_stat == TRUE) ? "success" : "failure",
+                 p->gr_ctx.value, p->gr_ctx.length,
+                 p->gr_major, p->gr_minor, p->gr_win,
+                 p->gr_token.value, p->gr_token.length);
+
+       return (xdr_stat);
+}
+
+bool_t
+xdr_rpc_gss_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
+                     gss_ctx_id_t ctx, gss_qop_t qop,
+                     rpc_gss_svc_t svc, u_int seq)
+{
+       gss_buffer_desc databuf, wrapbuf;
+       OM_uint32       maj_stat, min_stat;
+       int             start, end, conf_state;
+       bool_t          xdr_stat;
+
+       /* Skip databody length. */
+       start = XDR_GETPOS(xdrs);
+       XDR_SETPOS(xdrs, start + 4);
+
+       /* Marshal rpc_gss_data_t (sequence number + arguments). */
+       if (!xdr_u_int(xdrs, &seq) || !(*xdr_func)(xdrs, xdr_ptr))
+               return (FALSE);
+       end = XDR_GETPOS(xdrs);
+
+       /* Set databuf to marshalled rpc_gss_data_t. */
+       databuf.length = end - start - 4;
+       XDR_SETPOS(xdrs, start + 4);
+       databuf.value = XDR_INLINE(xdrs, databuf.length);
+
+       xdr_stat = FALSE;
+
+       if (svc == RPCSEC_GSS_SVC_INTEGRITY) {
+               /* Marshal databody_integ length. */
+               XDR_SETPOS(xdrs, start);
+               if (!xdr_u_int(xdrs, &databuf.length))
+                       return (FALSE);
+
+               /* Checksum rpc_gss_data_t. */
+               maj_stat = gss_get_mic(&min_stat, ctx, qop,
+                                      &databuf, &wrapbuf);
+               if (maj_stat != GSS_S_COMPLETE) {
+                       log_debug("gss_get_mic failed");
+                       return (FALSE);
+               }
+               /* Marshal checksum. */
+               XDR_SETPOS(xdrs, end);
+               xdr_stat = xdr_bytes(xdrs, (char **)&wrapbuf.value,
+                                    &wrapbuf.length, MAX_NETOBJ_SZ);
+               gss_release_buffer(&min_stat, &wrapbuf);
+       }
+       else if (svc == RPCSEC_GSS_SVC_PRIVACY) {
+               /* Encrypt rpc_gss_data_t. */
+               maj_stat = gss_wrap(&min_stat, ctx, TRUE, qop, &databuf,
+                                   &conf_state, &wrapbuf);
+               if (maj_stat != GSS_S_COMPLETE) {
+                       log_status("gss_wrap", maj_stat, min_stat);
+                       return (FALSE);
+               }
+               /* Marshal databody_priv. */
+               XDR_SETPOS(xdrs, start);
+               xdr_stat = xdr_bytes(xdrs, (char **)&wrapbuf.value,
+                                    &wrapbuf.length, MAX_NETOBJ_SZ);
+               gss_release_buffer(&min_stat, &wrapbuf);
+       }
+       return (xdr_stat);
+}
+
+bool_t
+xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
+                       gss_ctx_id_t ctx, gss_qop_t qop,
+                       rpc_gss_svc_t svc, u_int seq)
+{
+       XDR             tmpxdrs;
+       gss_buffer_desc databuf, wrapbuf;
+       OM_uint32       maj_stat, min_stat;
+       u_int           seq_num, conf_state, qop_state;
+       bool_t          xdr_stat;
+
+       if (xdr_func == xdr_void || xdr_ptr == NULL)
+               return (TRUE);
+
+       memset(&databuf, 0, sizeof(databuf));
+       memset(&wrapbuf, 0, sizeof(wrapbuf));
+
+       if (svc == RPCSEC_GSS_SVC_INTEGRITY) {
+               /* Decode databody_integ. */
+               if (!xdr_bytes(xdrs, (char **)&databuf.value, &databuf.length,
+                              MAX_NETOBJ_SZ)) {
+                       log_debug("xdr decode databody_integ failed");
+                       return (FALSE);
+               }
+               /* Decode checksum. */
+               if (!xdr_bytes(xdrs, (char **)&wrapbuf.value, &wrapbuf.length,
+                              MAX_NETOBJ_SZ)) {
+                       gss_release_buffer(&min_stat, &databuf);
+                       log_debug("xdr decode checksum failed");
+                       return (FALSE);
+               }
+               /* Verify checksum and QOP. */
+               maj_stat = gss_verify_mic(&min_stat, ctx, &databuf,
+                                         &wrapbuf, &qop_state);
+               gss_release_buffer(&min_stat, &wrapbuf);
+
+               if (maj_stat != GSS_S_COMPLETE || qop_state != qop) {
+                       gss_release_buffer(&min_stat, &databuf);
+                       log_status("gss_verify_mic", maj_stat, min_stat);
+                       return (FALSE);
+               }
+       }
+       else if (svc == RPCSEC_GSS_SVC_PRIVACY) {
+               /* Decode databody_priv. */
+               if (!xdr_bytes(xdrs, (char **)&wrapbuf.value, &wrapbuf.length,
+                              MAX_NETOBJ_SZ)) {
+                       log_debug("xdr decode databody_priv failed");
+                       return (FALSE);
+               }
+               /* Decrypt databody. */
+               maj_stat = gss_unwrap(&min_stat, ctx, &wrapbuf, &databuf,
+                                     &conf_state, &qop_state);
+
+               gss_release_buffer(&min_stat, &wrapbuf);
+
+               /* Verify encryption and QOP. */
+               if (maj_stat != GSS_S_COMPLETE || qop_state != qop ||
+                       conf_state != TRUE) {
+                       gss_release_buffer(&min_stat, &databuf);
+                       log_status("gss_unwrap", maj_stat, min_stat);
+                       return (FALSE);
+               }
+       }
+       /* Decode rpc_gss_data_t (sequence number + arguments). */
+       xdrmem_create(&tmpxdrs, databuf.value, databuf.length, XDR_DECODE);
+       xdr_stat = (xdr_u_int(&tmpxdrs, &seq_num) &&
+                   (*xdr_func)(&tmpxdrs, xdr_ptr));
+       XDR_DESTROY(&tmpxdrs);
+       gss_release_buffer(&min_stat, &databuf);
+
+       /* Verify sequence number. */
+       if (xdr_stat == TRUE && seq_num != seq) {
+               log_debug("wrong sequence number in databody");
+               return (FALSE);
+       }
+       return (xdr_stat);
+}
+
+bool_t
+xdr_rpc_gss_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr,
+                gss_ctx_id_t ctx, gss_qop_t qop,
+                rpc_gss_svc_t svc, u_int seq)
+{
+       switch (xdrs->x_op) {
+
+       case XDR_ENCODE:
+               return (xdr_rpc_gss_wrap_data(xdrs, xdr_func, xdr_ptr,
+                                             ctx, qop, svc, seq));
+       case XDR_DECODE:
+               return (xdr_rpc_gss_unwrap_data(xdrs, xdr_func, xdr_ptr,
+                                               ctx, qop,svc, seq));
+       case XDR_FREE:
+               return (TRUE);
+       }
+       return (FALSE);
+}
+
+#ifdef DEBUG
+#include <ctype.h>
+
+void
+log_debug(const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       fprintf(stderr, "rpcsec_gss: ");
+       vfprintf(stderr, fmt, ap);
+       fprintf(stderr, "\n");
+       va_end(ap);
+}
+
+void
+log_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat)
+{
+       OM_uint32 min;
+       gss_buffer_desc msg;
+       int msg_ctx = 0;
+
+       fprintf(stderr, "rpcsec_gss: %s: ", m);
+
+       gss_display_status(&min, maj_stat, GSS_C_GSS_CODE, GSS_C_NULL_OID,
+                          &msg_ctx, &msg);
+       fprintf(stderr, "%s - ", (char *)msg.value);
+       gss_release_buffer(&min, &msg);
+
+       gss_display_status(&min, min_stat, GSS_C_MECH_CODE, GSS_C_NULL_OID,
+                          &msg_ctx, &msg);
+       fprintf(stderr, "%s\n", (char *)msg.value);
+       gss_release_buffer(&min, &msg);
+}
+
+void
+log_hexdump(const u_char *buf, int len, int offset)
+{
+       u_int i, j, jm;
+       int c;
+
+       fprintf(stderr, "\n");
+       for (i = 0; i < len; i += 0x10) {
+               fprintf(stderr, "  %04x: ", (u_int)(i + offset));
+               jm = len - i;
+               jm = jm > 16 ? 16 : jm;
+
+               for (j = 0; j < jm; j++) {
+                       if ((j % 2) == 1)
+                               fprintf(stderr, "%02x ", (u_int) buf[i+j]);
+                       else
+                               fprintf(stderr, "%02x", (u_int) buf[i+j]);
+               }
+               for (; j < 16; j++) {
+                       if ((j % 2) == 1) printf("   ");
+                       else fprintf(stderr, "  ");
+               }
+               fprintf(stderr, " ");
+
+               for (j = 0; j < jm; j++) {
+                       c = buf[i+j];
+             &nb