summaryrefslogtreecommitdiff
path: root/usr/src/lib/libgss
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libgss
downloadillumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libgss')
-rw-r--r--usr/src/lib/libgss/Makefile100
-rw-r--r--usr/src/lib/libgss/Makefile.com118
-rw-r--r--usr/src/lib/libgss/README.spi119
-rw-r--r--usr/src/lib/libgss/amd64/Makefile37
-rw-r--r--usr/src/lib/libgss/g_accept_sec_context.c318
-rw-r--r--usr/src/lib/libgss/g_acquire_cred.c442
-rw-r--r--usr/src/lib/libgss/g_acquire_cred_with_pw.c437
-rw-r--r--usr/src/lib/libgss/g_canon_name.c176
-rw-r--r--usr/src/lib/libgss/g_compare_name.c183
-rw-r--r--usr/src/lib/libgss/g_context_time.c81
-rw-r--r--usr/src/lib/libgss/g_delete_sec_context.c88
-rw-r--r--usr/src/lib/libgss/g_dsp_name.c112
-rw-r--r--usr/src/lib/libgss/g_dsp_status.c367
-rw-r--r--usr/src/lib/libgss/g_dup_name.c139
-rw-r--r--usr/src/lib/libgss/g_exp_sec_context.c113
-rw-r--r--usr/src/lib/libgss/g_export_name.c76
-rw-r--r--usr/src/lib/libgss/g_glue.c586
-rw-r--r--usr/src/lib/libgss/g_imp_name.c336
-rw-r--r--usr/src/lib/libgss/g_imp_sec_context.c137
-rw-r--r--usr/src/lib/libgss/g_init_sec_context.c207
-rw-r--r--usr/src/lib/libgss/g_initialize.c938
-rw-r--r--usr/src/lib/libgss/g_inquire_context.c141
-rw-r--r--usr/src/lib/libgss/g_inquire_cred.c260
-rw-r--r--usr/src/lib/libgss/g_inquire_names.c162
-rw-r--r--usr/src/lib/libgss/g_oid_ops.c88
-rw-r--r--usr/src/lib/libgss/g_process_context.c82
-rw-r--r--usr/src/lib/libgss/g_rel_buffer.c60
-rw-r--r--usr/src/lib/libgss/g_rel_cred.c100
-rw-r--r--usr/src/lib/libgss/g_rel_name.c83
-rw-r--r--usr/src/lib/libgss/g_rel_oid_set.c66
-rw-r--r--usr/src/lib/libgss/g_seal.c169
-rw-r--r--usr/src/lib/libgss/g_sign.c110
-rw-r--r--usr/src/lib/libgss/g_store_cred.c157
-rw-r--r--usr/src/lib/libgss/g_unseal.c120
-rw-r--r--usr/src/lib/libgss/g_userok.c133
-rw-r--r--usr/src/lib/libgss/g_utils.c302
-rw-r--r--usr/src/lib/libgss/g_verify.c106
-rw-r--r--usr/src/lib/libgss/gssd_pname_to_uid.c569
-rw-r--r--usr/src/lib/libgss/i386/Makefile38
-rw-r--r--usr/src/lib/libgss/inc.flg30
-rw-r--r--usr/src/lib/libgss/llib-lgss32
-rw-r--r--usr/src/lib/libgss/oid_ops.c516
-rw-r--r--usr/src/lib/libgss/req.flg31
-rw-r--r--usr/src/lib/libgss/sparc/Makefile37
-rw-r--r--usr/src/lib/libgss/sparcv9/Makefile38
-rw-r--r--usr/src/lib/libgss/spec/Makefile30
-rw-r--r--usr/src/lib/libgss/spec/Makefile.targ36
-rw-r--r--usr/src/lib/libgss/spec/amd64/Makefile42
-rw-r--r--usr/src/lib/libgss/spec/gss.spec753
-rw-r--r--usr/src/lib/libgss/spec/i386/Makefile42
-rw-r--r--usr/src/lib/libgss/spec/sparc/Makefile44
-rw-r--r--usr/src/lib/libgss/spec/sparcv9/Makefile43
-rw-r--r--usr/src/lib/libgss/spec/versions47
53 files changed, 9577 insertions, 0 deletions
diff --git a/usr/src/lib/libgss/Makefile b/usr/src/lib/libgss/Makefile
new file mode 100644
index 0000000000..a1c813540e
--- /dev/null
+++ b/usr/src/lib/libgss/Makefile
@@ -0,0 +1,100 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libgss/Makefile
+#
+include ../Makefile.lib
+
+LIBRARY= libgss.a
+
+# defines the duplicate sources we share with gsscred
+GSSCRED_DIR = $(SRC)/cmd/gss/gsscred
+DUPLICATE_SRC = gsscred_utils.c gsscred_file.c # gen_oids.c
+CLEAN_SRC = $(DUPLICATE_SRC) gen_oids.c
+
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+ROOTDIRS= $(ROOT)/usr/include
+GSSMECH_DIR= $(ROOT)/usr/lib/gss
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+lint := TARGET= lint
+
+POFILE = $(LIBRARY:.a=.po)
+XGETFLAGS+= -a
+MSGFILES = `$(GREP) -l gettext *.[ch]`
+
+.KEEP_STATE:
+
+all clean clobber install: spec .WAIT $(SUBDIRS)
+
+lint: $(SUBDIRS)
+
+install: $(GSSMECH_DIR) all .WAIT $(SUBDIRS)
+
+check install_h:
+
+_msg: $(MSGDOMAINPOFILE)
+
+$(POFILE): pofile_MSGFILES
+
+$(GSSMECH_DIR):
+ $(INS.dir)
+
+$(SUBDIRS) spec: FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+# include library targets
+include ../Makefile.targ
+
+# EXPORT DELETE START
+# Special target to clean up the source tree for export distribution
+# Warning: This target changes the source tree
+
+EXPORT_SRC:
+ $(RM) Makefile+ g_seal.c+ g_unseal.c+
+ sed -e "/EXPORT DELETE START/,/EXPORT DELETE END/d" \
+ < g_seal.c > g_seal.c+
+ $(MV) g_seal.c+ g_seal.c
+ sed -e "/EXPORT DELETE START/,/EXPORT DELETE END/d" \
+ < g_unseal.c > g_unseal.c+
+ $(MV) g_unseal.c+ g_unseal.c
+ sed -e "/^# EXPORT DELETE START/,/^# EXPORT DELETE END/d" \
+ < Makefile > Makefile+
+ $(MV) Makefile+ Makefile
+ $(CHMOD) 444 Makefile g_seal.c g_unseal.c
+
+# EXPORT DELETE END
+
+
+include $(SRC)/Makefile.msg.targ
diff --git a/usr/src/lib/libgss/Makefile.com b/usr/src/lib/libgss/Makefile.com
new file mode 100644
index 0000000000..03733a1d0a
--- /dev/null
+++ b/usr/src/lib/libgss/Makefile.com
@@ -0,0 +1,118 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libgss/Makefile
+
+LIBRARY = libgss.a
+VERS = .1
+
+GSSOBJECTS = g_acquire_cred.o \
+ g_acquire_cred_with_pw.o \
+ g_store_cred.o \
+ g_rel_cred.o \
+ g_init_sec_context.o \
+ g_accept_sec_context.o \
+ g_process_context.o \
+ g_delete_sec_context.o \
+ g_imp_sec_context.o \
+ g_exp_sec_context.o \
+ g_context_time.o \
+ g_sign.o \
+ g_verify.o \
+ g_seal.o \
+ g_unseal.o \
+ g_dsp_status.o \
+ g_compare_name.o \
+ g_dsp_name.o \
+ g_imp_name.o \
+ g_rel_name.o \
+ g_rel_buffer.o \
+ g_rel_oid_set.o \
+ g_oid_ops.o \
+ g_inquire_cred.o \
+ g_inquire_context.o \
+ g_inquire_names.o \
+ g_initialize.o \
+ g_glue.o \
+ gssd_pname_to_uid.o \
+ oid_ops.o \
+ g_canon_name.o \
+ g_dup_name.o \
+ g_export_name.o \
+ g_utils.o \
+ g_userok.o
+
+
+# defines the duplicate sources we share with gsscred
+GSSCRED_DIR = $(SRC)/cmd/gss/gsscred
+GSSCREDOBJ = gsscred_utils.o gsscred_file.o
+UTSGSSDIR = $(SRC)/uts/common/gssapi
+UTSGSSOBJ = gen_oids.o
+SRCS += $(GSSCREDOBJ:%.o=$(GSSCRED_DIR)/%.c) \
+ $(UTSGSSOBJ:%.o=$(UTSGSSDIR)/%.c)
+GSSLINTSRC = $(GSSOBJECTS:%.o=$(SRCDIR)/%.c) \
+ $(GSSCREDOBJ:%.o=$(GSSCRED_DIR)/%.c) \
+ $(UTSGSSOBJ:%.o=$(UTSGSSDIR)/%.c)
+OBJECTS = $(GSSOBJECTS) $(GSSCREDOBJ) $(UTSGSSOBJ)
+
+# include library definitions
+include ../../Makefile.lib
+
+LIBS = $(DYNLIB) $(LINTLIB)
+
+$(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC)
+LDLIBS += -lc -lcmd
+
+SRCDIR = ..
+MAPDIR = ../spec/$(TRANSMACH)
+SPECMAPFILE= $(MAPDIR)/mapfile
+
+CPPFLAGS += -I$(GSSCRED_DIR) -I$(SRC)/uts/common/gssapi/include \
+ -DHAVE_STDLIB_H
+
+$(EXPORT_RELEASE_BUILD)include ../Makefile.export
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lintcheck:= SRCS= $(GSSLINTSRC)
+
+lint: lintcheck
+
+$(GSSCREDOBJ:%.o=pics/%.o):
+ $(COMPILE.c) -o $@ $(@:pics/%.o=$(GSSCRED_DIR)/%.c)
+ $(POST_PROCESS_O)
+
+# gen_oids.c is kept in the kernel since the OIDs declared in them are
+# used by rpcsec module
+pics/gen_oids.o: $(SRC)/uts/common/gssapi/gen_oids.c
+ $(COMPILE.c) -o $@ $(SRC)/uts/common/gssapi/gen_oids.c
+ $(POST_PROCESS_O)
+
+# include library targets
+include ../../Makefile.targ
diff --git a/usr/src/lib/libgss/README.spi b/usr/src/lib/libgss/README.spi
new file mode 100644
index 0000000000..a6fa349229
--- /dev/null
+++ b/usr/src/lib/libgss/README.spi
@@ -0,0 +1,119 @@
+
+ CDDL HEADER START
+
+ The contents of this file are subject to the terms of the
+ Common Development and Distribution License, Version 1.0 only
+ (the "License"). You may not use this file except in compliance
+ with the License.
+
+ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ or http://www.opensolaris.org/os/licensing.
+ See the License for the specific language governing permissions
+ and limitations under the License.
+
+ When distributing Covered Code, include this CDDL HEADER in each
+ file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ If applicable, add the following below this CDDL HEADER, with the
+ fields enclosed by brackets "[]" replaced with your own identifying
+ information: Portions Copyright [yyyy] [name of copyright owner]
+
+ CDDL HEADER END
+
+ Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ Use is subject to license terms.
+
+#ident "%Z%%M% %I% %E% SMI"
+
+
+ The Service Provider Interface for libgss and its Mechanisms
+ ------------------------------------------------------------
+
+/* CRYPT DELETE START */
+
+1. The libgss SPI upto 11/2004
+
+ Prior to PSARC 2004/810 the libgss SPI consisted of a function
+ provided by each mechanism whose return value is a pointer to a
+ structure full of references to the mechanism's entry points
+ (hereinafter: methods).
+
+ This structure does not include any hooks for versioning, which
+ means that additions of any mechanism methods at micro/patch
+ releases require patching libgss.so.1 and all the GSS mechanisms
+ shipped with Solaris (Kerberos V, DH, SPNEGO).
+
+2. The libgss SPI after PSARC 2004/810
+
+ In order to avoid changing the gss_config struct and patching all
+ three mechanisms (four, if the dummy mech counts) and libgss
+ together and in anticipation of a cleaner SPI in the future (see
+ next section) the SPI after PSARC 2004/810 will be as before but
+ supplemented as follows:
+
+ - any new SPI mechanism methods will NOT be placed in gss_config,
+ instead there is a new gss_config_ext structure, which is to be
+ used _only_ by libgss (to avoid struct versioning and/or patch
+ issues), which should be extended to have a pointer to the new
+ method;
+
+ - there is a new libgss function, __gss_get_mechanism_ext(), which
+ is used to get at the gss_config_ext for a mechanism;
+
+ - __gss_get_mechanism_ext() uses dlsym() to build the
+ gss_config_ext struct for the mech by individually loading each
+ and every mechanism method that isn't part of the old gss_config
+ struct -- this happens only once per-method, of course; the
+ result is cached.
+
+ The symbol names that are dlsym()ed are of the form gssspi_* and
+ correspond to gss_*; e.g., gssspi_acquire_cred_with_password().
+
+ New methods also have a corresponding typedef named
+ <gss_func>_sfct -- the 's' in 'sfct' is for "SPI" and the 'fct'
+ is for "function." This is used to keep cast expressions short.
+
+3. The Future libgss SPI
+
+ Once the Solaris krb5 source is resync'ed with MIT krb5 1.4 there
+ will be no further need for the 'void *context' argument to all the
+ libgss mechanisms' methods.
+
+ At that point it will be possible to remove this 'void *context'
+ argument from all the libgss SPI function prototypes, the main
+ result of which will be that the mechanisms' methods will then have
+ the same function signature as the corresponding GSS-API functions.
+
+ We can then rename all mechanisms' methods from <mech>_<gss-func> to
+ <gss-func>. The corresponding typedefs will be renamed to
+ <gss-func>_fct.
+
+ The SPI, then, will be almost exactly the same as the API.
+
+ There will be some minor differences, primarily that some API
+ functions won't have a corresponding SPI method, such as
+ gss_release_buffer(3GSS), for example.
+
+ Some time later we may open the SPI to third party implementors;
+ this could be particularly useful as a way to get access to 3rd
+ party implementations of SPKM and LIPKEY (assuming any ever exist --
+ SPKM's is a very problematic specification).
+
+ Third party mechanisms should just export all the symbols for the
+ GSS-API functions, like MIT krb5 does, but functions which libgss
+ won't call (e.g., gss_release_buffer(3GSS)) should either not be
+ implemented or should be weak symbols.
+
+ Solaris native mechanisms may still provide the mechanism method
+ registration function as usual for optimization purposes -- to
+ reduce the number of calls to dlsym().
+
+ Mechanisms that do not provide the old method registration function
+ will be loaded as follows:
+
+ - libgss will look for and find the mechanism's
+ GSS_Indicate_mechs() method and will call it to discover the
+ mechanism provider's mechanism OIDs.
+
+ - libgss will dlsym() each mechanism provider SPI method.
+
+/* CRYPT DELETE END */
diff --git a/usr/src/lib/libgss/amd64/Makefile b/usr/src/lib/libgss/amd64/Makefile
new file mode 100644
index 0000000000..717a2abbca
--- /dev/null
+++ b/usr/src/lib/libgss/amd64/Makefile
@@ -0,0 +1,37 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+GSSMECH_DIR_V9 = $(ROOT)/usr/lib/amd64/gss
+
+install: all $(GSSMECH_DIR_V9) $(ROOTLIBS64) $(ROOTLINKS64)
+
+$(GSSMECH_DIR_V9):
+ $(INS.dir)
diff --git a/usr/src/lib/libgss/g_accept_sec_context.c b/usr/src/lib/libgss/g_accept_sec_context.c
new file mode 100644
index 0000000000..442d472f47
--- /dev/null
+++ b/usr/src/lib/libgss/g_accept_sec_context.c
@@ -0,0 +1,318 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine for gss_accept_sec_context
+ */
+
+#include <mechglueP.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+OM_uint32
+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,
+ d_cred)
+
+OM_uint32 *minor_status;
+gss_ctx_id_t *context_handle;
+const gss_cred_id_t verifier_cred_handle;
+const gss_buffer_t input_token_buffer;
+const 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 *d_cred; /* 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_cred_id_t tmp_d_cred = GSS_C_NO_CREDENTIAL;
+ gss_name_t internal_name = GSS_C_NO_NAME;
+ gss_name_t tmp_src_name = GSS_C_NO_NAME;
+ gss_OID_desc token_mech_type_desc;
+ gss_OID token_mech_type = &token_mech_type_desc;
+ gss_mechanism mech;
+
+ /* check parameters first */
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (context_handle == NULL || output_token == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ /* clear optional fields */
+ output_token->value = NULL;
+ output_token->length = 0;
+ if (src_name)
+ *src_name = NULL;
+
+ if (mech_type)
+ *mech_type = NULL;
+
+ if (d_cred)
+ *d_cred = NULL;
+ /*
+ * 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) {
+
+ if (GSS_EMPTY_BUFFER(input_token_buffer))
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ /* 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)
+ return (GSS_S_FAILURE);
+
+ union_ctx_id->internal_ctx_id = GSS_C_NO_CONTEXT;
+ status = generic_gss_copy_oid(&temp_minor_status,
+ token_mech_type,
+ &union_ctx_id->mech_type);
+ if (status != GSS_S_COMPLETE) {
+ free(union_ctx_id);
+ return (status);
+ }
+
+ /* set the new context handle to caller's data */
+ *context_handle = (gss_ctx_id_t)union_ctx_id;
+ } else {
+ union_ctx_id = (gss_union_ctx_id_t)*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(
+ mech->context,
+ 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,
+ d_cred ? &tmp_d_cred : NULL);
+
+ /* 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 (internal_name != NULL) {
+ temp_status = __gss_convert_name_to_union_name(
+ &temp_minor_status, mech,
+ internal_name, &tmp_src_name);
+ if (temp_status != GSS_S_COMPLETE) {
+ *minor_status = temp_minor_status;
+ if (output_token->length)
+ (void) gss_release_buffer(
+ &temp_minor_status,
+ output_token);
+ if (internal_name != GSS_C_NO_NAME)
+ mech->gss_release_name(
+ mech->context,
+ &temp_minor_status,
+ &internal_name);
+ return (temp_status);
+ }
+ if (src_name != NULL) {
+ *src_name = tmp_src_name;
+ }
+ } else if (src_name != NULL) {
+ *src_name = GSS_C_NO_NAME;
+ }
+
+ /* Ensure we're returning correct creds format */
+ if ((ret_flags && GSS_C_DELEG_FLAG) &&
+ tmp_d_cred != GSS_C_NO_CREDENTIAL) {
+ gss_union_cred_t d_u_cred = NULL;
+
+ d_u_cred = malloc(sizeof (gss_union_cred_desc));
+ if (d_u_cred == NULL) {
+ status = GSS_S_FAILURE;
+ goto error_out;
+ }
+ (void) memset(d_u_cred, 0,
+ sizeof (gss_union_cred_desc));
+
+ d_u_cred->count = 1;
+
+ status = generic_gss_copy_oid(&temp_minor_status,
+ token_mech_type,
+ &d_u_cred->mechs_array);
+
+ if (status != GSS_S_COMPLETE) {
+ free(d_u_cred);
+ goto error_out;
+ }
+
+ d_u_cred->cred_array = malloc(sizeof (gss_cred_id_t));
+ if (d_u_cred->cred_array != NULL) {
+ d_u_cred->cred_array[0] = tmp_d_cred;
+ } else {
+ free(d_u_cred);
+ status = GSS_S_FAILURE;
+ goto error_out;
+ }
+
+ if (status != GSS_S_COMPLETE) {
+ free(d_u_cred->cred_array);
+ free(d_u_cred);
+ goto error_out;
+ }
+
+ internal_name = GSS_C_NO_NAME;
+
+ d_u_cred->auxinfo.creation_time = time(0);
+ d_u_cred->auxinfo.time_rec = 0;
+
+ if (mech->gss_inquire_cred) {
+ status = mech->gss_inquire_cred(mech->context,
+ minor_status,
+ tmp_d_cred,
+ &internal_name,
+ &d_u_cred->auxinfo.time_rec,
+ &d_u_cred->auxinfo.cred_usage,
+ NULL);
+ }
+
+ if (internal_name != NULL) {
+ temp_status = __gss_convert_name_to_union_name(
+ &temp_minor_status, mech,
+ internal_name, &tmp_src_name);
+ if (temp_status != GSS_S_COMPLETE) {
+ *minor_status = temp_minor_status;
+ if (output_token->length)
+ (void) gss_release_buffer(
+ &temp_minor_status,
+ output_token);
+ free(d_u_cred->cred_array);
+ free(d_u_cred);
+ return (temp_status);
+ }
+ }
+
+ if (tmp_src_name != NULL) {
+ status = gss_display_name(
+ &temp_minor_status,
+ tmp_src_name,
+ &d_u_cred->auxinfo.name,
+ &d_u_cred->auxinfo.name_type);
+ }
+
+ *d_cred = (gss_cred_id_t)d_u_cred;
+ }
+
+ if (src_name == NULL && tmp_src_name != NULL)
+ (void) gss_release_name(&temp_minor_status,
+ &tmp_src_name);
+ return (status);
+ } else {
+
+ status = 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);
+ *context_handle = GSS_C_NO_CONTEXT;
+ }
+
+ if (output_token->length)
+ (void) gss_release_buffer(&temp_minor_status, output_token);
+
+ if (src_name)
+ *src_name = GSS_C_NO_NAME;
+
+ if (tmp_src_name != GSS_C_NO_NAME)
+ (void) gss_release_buffer(&temp_minor_status,
+ (gss_buffer_t)tmp_src_name);
+
+ return (status);
+}
diff --git a/usr/src/lib/libgss/g_acquire_cred.c b/usr/src/lib/libgss/g_acquire_cred.c
new file mode 100644
index 0000000000..a6ecd5a533
--- /dev/null
+++ b/usr/src/lib/libgss/g_acquire_cred.c
@@ -0,0 +1,442 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine for gss_acquire_cred
+ */
+
+#include <mechglueP.h>
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+/* local functions */
+static gss_OID_set create_actual_mechs(const gss_OID, int);
+
+static gss_OID_set
+create_actual_mechs(mechs_array, count)
+ const gss_OID mechs_array;
+ int count;
+{
+ gss_OID_set actual_mechs;
+ int i;
+ OM_uint32 minor;
+
+ 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) * count);
+ if (!actual_mechs->elements) {
+ free(actual_mechs);
+ return (NULL);
+ }
+
+ actual_mechs->count = 0;
+
+ for (i = 0; i < count; i++) {
+ actual_mechs->elements[i].elements = (void *)
+ malloc(mechs_array[i].length);
+ if (actual_mechs->elements[i].elements == NULL) {
+ (void) gss_release_oid_set(&minor, &actual_mechs);
+ return (NULL);
+ }
+ g_OID_copy(&actual_mechs->elements[i], &mechs_array[i]);
+ actual_mechs->count++;
+ }
+
+ return (actual_mechs);
+}
+
+
+OM_uint32
+gss_acquire_cred(minor_status,
+ desired_name,
+ time_req,
+ desired_mechs,
+ cred_usage,
+ output_cred_handle,
+ actual_mechs,
+ time_rec)
+
+OM_uint32 * minor_status;
+const gss_name_t desired_name;
+OM_uint32 time_req;
+const 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 major = GSS_S_FAILURE;
+ OM_uint32 initTimeOut, acceptTimeOut, outTime = GSS_C_INDEFINITE;
+ gss_OID_set_desc default_OID_set;
+ gss_OID_set mechs;
+ gss_OID_desc default_OID;
+ gss_mechanism mech;
+ int i;
+ gss_union_cred_t creds;
+
+ /* start by checking parameters */
+ if (!minor_status)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (!output_cred_handle)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED);
+
+ *output_cred_handle = GSS_C_NO_CREDENTIAL;
+
+ /* Set output parameters to NULL for now */
+ if (actual_mechs)
+ *actual_mechs = GSS_C_NULL_OID_SET;
+
+ if (time_rec)
+ *time_rec = 0;
+
+ /*
+ * if desired_mechs equals GSS_C_NULL_OID_SET, then pick an
+ * appropriate default. We use the first mechanism in the
+ * mechansim list as the default. This set is created with
+ * statics thus needs not be freed
+ */
+ if (desired_mechs == GSS_C_NULL_OID_SET) {
+ mech = __gss_get_mechanism(NULL);
+ if (mech == NULL)
+ return (GSS_S_BAD_MECH);
+
+ 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;
+ } else
+ mechs = desired_mechs;
+
+ if (mechs->count == NULL)
+ return (GSS_S_BAD_MECH);
+
+ /* allocate the output credential structure */
+ creds = (gss_union_cred_t)malloc(sizeof (gss_union_cred_desc));
+ if (creds == NULL)
+ return (GSS_S_FAILURE);
+
+ /* initialize to 0s */
+ (void) memset(creds, 0, sizeof (gss_union_cred_desc));
+
+ /* for each requested mech attempt to obtain a credential */
+ for (i = 0; i < mechs->count; i++) {
+ major = gss_add_cred(minor_status, (gss_cred_id_t)creds,
+ desired_name,
+ &mechs->elements[i],
+ cred_usage, time_req, time_req, NULL,
+ NULL, &initTimeOut, &acceptTimeOut);
+ if (major == GSS_S_COMPLETE) {
+ /* update the credential's time */
+ if (cred_usage == GSS_C_ACCEPT) {
+ if (outTime > acceptTimeOut)
+ outTime = acceptTimeOut;
+ } else if (cred_usage == GSS_C_INITIATE) {
+ if (outTime > initTimeOut)
+ outTime = initTimeOut;
+ } else {
+ /*
+ * time_rec is the lesser of the
+ * init/accept times
+ */
+ if (initTimeOut > acceptTimeOut)
+ outTime = (outTime > acceptTimeOut) ?
+ acceptTimeOut : outTime;
+ else
+ outTime = (outTime > initTimeOut) ?
+ initTimeOut : outTime;
+ }
+ }
+ } /* for */
+
+ /* ensure that we have at least one credential element */
+ if (creds->count < 1) {
+ free(creds);
+ return (major);
+ }
+
+ /*
+ * fill in output parameters
+ * setup the actual mechs output parameter
+ */
+ if (actual_mechs != NULL) {
+ if ((*actual_mechs = create_actual_mechs(creds->mechs_array,
+ creds->count)) == NULL) {
+ (void) gss_release_cred(minor_status,
+ (gss_cred_id_t *)&creds);
+ *minor_status = 0;
+ return (GSS_S_FAILURE);
+ }
+ }
+
+ if (time_rec)
+ *time_rec = outTime;
+
+
+ *output_cred_handle = (gss_cred_id_t)creds;
+ return (GSS_S_COMPLETE);
+}
+
+/* V2 INTERFACE */
+OM_uint32
+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;
+ const gss_cred_id_t input_cred_handle;
+ const gss_name_t desired_name;
+ const 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, time_req, time_rec, temp_minor_status;
+ gss_mechanism mech;
+ gss_union_name_t union_name = NULL;
+ gss_union_cred_t union_cred, new_union_cred;
+ gss_name_t internal_name = GSS_C_NO_NAME;
+ gss_name_t allocated_name = GSS_C_NO_NAME;
+ gss_cred_id_t cred = NULL;
+ gss_OID new_mechs_array = NULL;
+ gss_cred_id_t *new_cred_array = NULL;
+
+ /* check input parameters */
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (input_cred_handle == GSS_C_NO_CREDENTIAL &&
+ output_cred_handle == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED);
+
+ if (output_cred_handle)
+ *output_cred_handle = GSS_C_NO_CREDENTIAL;
+
+ if (actual_mechs)
+ *actual_mechs = NULL;
+
+ if (acceptor_time_rec)
+ *acceptor_time_rec = 0;
+
+ if (initiator_time_rec)
+ *initiator_time_rec = 0;
+
+ mech = __gss_get_mechanism(desired_mech);
+ if (!mech)
+ return (GSS_S_BAD_MECH);
+ else if (!mech->gss_acquire_cred)
+ return (GSS_S_UNAVAILABLE);
+
+ if (input_cred_handle == GSS_C_NO_CREDENTIAL) {
+ union_cred = malloc(sizeof (gss_union_cred_desc));
+ if (union_cred == NULL)
+ return (GSS_S_FAILURE);
+
+ (void) memset(union_cred, 0, sizeof (gss_union_cred_desc));
+
+ /* for default credentials we will use GSS_C_NO_NAME */
+ internal_name = GSS_C_NO_NAME;
+ } else {
+ union_cred = (gss_union_cred_t)input_cred_handle;
+ if (__gss_get_mechanism_cred(union_cred, desired_mech) !=
+ GSS_C_NO_CREDENTIAL)
+ return (GSS_S_DUPLICATE_ELEMENT);
+
+ /* may need to create a mechanism specific name */
+ if (desired_name) {
+ union_name = (gss_union_name_t)desired_name;
+ if (union_name->mech_type &&
+ g_OID_equal(union_name->mech_type,
+ &mech->mech_type))
+ internal_name = union_name->mech_name;
+ else {
+ if (__gss_import_internal_name(minor_status,
+ &mech->mech_type, union_name,
+ &allocated_name) != GSS_S_COMPLETE)
+ return (GSS_S_BAD_NAME);
+ internal_name = allocated_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;
+
+ status = mech->gss_acquire_cred(mech->context, minor_status,
+ internal_name, time_req,
+ GSS_C_NULL_OID_SET, cred_usage,
+ &cred, NULL, &time_rec);
+
+ if (status != GSS_S_COMPLETE)
+ goto errout;
+
+ /* may need to set credential auxinfo strucutre */
+ if (union_cred->auxinfo.creation_time == 0) {
+ union_cred->auxinfo.creation_time = time(NULL);
+ union_cred->auxinfo.time_rec = time_rec;
+ union_cred->auxinfo.cred_usage = cred_usage;
+
+ /*
+ * we must set the name; if name is not supplied
+ * we must do inquire cred to get it
+ */
+ if (internal_name == NULL) {
+ if (mech->gss_inquire_cred == NULL ||
+ ((status = mech->gss_inquire_cred(
+ mech->context,
+ &temp_minor_status, cred,
+ &allocated_name, NULL, NULL,
+ NULL)) != GSS_S_COMPLETE))
+ goto errout;
+ internal_name = allocated_name;
+ }
+
+ if ((status = mech->gss_display_name(mech->context,
+ &temp_minor_status, internal_name,
+ &union_cred->auxinfo.name,
+ &union_cred->auxinfo.name_type)) !=
+ GSS_S_COMPLETE)
+ goto errout;
+ }
+
+ /* now add the new credential elements */
+ 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) {
+ 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 and the credential array
+ */
+ (void) memcpy(new_mechs_array, union_cred->mechs_array,
+ sizeof (gss_OID_desc) * union_cred->count);
+ (void) memcpy(new_cred_array, union_cred->cred_array,
+ sizeof (gss_cred_id_t) * union_cred->count);
+
+ new_cred_array[union_cred->count] = cred;
+ if ((new_mechs_array[union_cred->count].elements =
+ malloc(mech->mech_type.length)) == NULL)
+ goto errout;
+
+ g_OID_copy(&new_mechs_array[union_cred->count],
+ &mech->mech_type);
+
+ if (actual_mechs) {
+ *actual_mechs = create_actual_mechs(new_mechs_array,
+ union_cred->count + 1);
+ if (*actual_mechs == NULL) {
+ free(new_mechs_array[union_cred->count].elements);
+ goto errout;
+ }
+ }
+
+ 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) {
+ free(new_mechs_array[union_cred->count].elements);
+ goto errout;
+ }
+ *new_union_cred = *union_cred;
+ *output_cred_handle = (gss_cred_id_t)new_union_cred;
+ }
+
+ new_union_cred->mechs_array = new_mechs_array;
+ new_union_cred->cred_array = new_cred_array;
+ new_union_cred->count++;
+
+ /* We're done with the internal name. Free it if we allocated it. */
+
+ if (allocated_name)
+ (void) __gss_release_internal_name(&temp_minor_status,
+ &mech->mech_type,
+ &allocated_name);
+
+ return (GSS_S_COMPLETE);
+
+errout:
+ if (new_mechs_array)
+ free(new_mechs_array);
+ if (new_cred_array)
+ free(new_cred_array);
+
+ if (cred != NULL && mech->gss_release_cred)
+ mech->gss_release_cred(mech->context,
+ &temp_minor_status, &cred);
+
+ if (allocated_name)
+ (void) __gss_release_internal_name(&temp_minor_status,
+ &mech->mech_type,
+ &allocated_name);
+
+ if (input_cred_handle == GSS_C_NO_CREDENTIAL && union_cred) {
+ if (union_cred->auxinfo.name.value)
+ free(union_cred->auxinfo.name.value);
+ free(union_cred);
+ }
+
+ return (status);
+}
diff --git a/usr/src/lib/libgss/g_acquire_cred_with_pw.c b/usr/src/lib/libgss/g_acquire_cred_with_pw.c
new file mode 100644
index 0000000000..778e550e49
--- /dev/null
+++ b/usr/src/lib/libgss/g_acquire_cred_with_pw.c
@@ -0,0 +1,437 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine for gss_acquire_cred
+ */
+
+#include <mechglueP.h>
+#include <gssapi/gssapi_ext.h>
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+/* local functions */
+static gss_OID_set create_actual_mechs(const gss_OID, int);
+
+static gss_OID_set
+create_actual_mechs(mechs_array, count)
+ const gss_OID mechs_array;
+ int count;
+{
+ gss_OID_set actual_mechs;
+ int i;
+ OM_uint32 minor;
+
+ 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) * count);
+ if (!actual_mechs->elements) {
+ free(actual_mechs);
+ return (NULL);
+ }
+
+ actual_mechs->count = 0;
+
+ for (i = 0; i < count; i++) {
+ actual_mechs->elements[i].elements = (void *)
+ malloc(mechs_array[i].length);
+ if (actual_mechs->elements[i].elements == NULL) {
+ (void) gss_release_oid_set(&minor, &actual_mechs);
+ return (NULL);
+ }
+ g_OID_copy(&actual_mechs->elements[i], &mechs_array[i]);
+ actual_mechs->count++;
+ }
+
+ return (actual_mechs);
+}
+
+
+OM_uint32
+gss_acquire_cred_with_password(minor_status,
+ desired_name,
+ password,
+ time_req,
+ desired_mechs,
+ cred_usage,
+ output_cred_handle,
+ actual_mechs,
+ time_rec)
+
+OM_uint32 * minor_status;
+const gss_name_t desired_name;
+const gss_buffer_t password;
+OM_uint32 time_req;
+const 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 major = GSS_S_FAILURE;
+ OM_uint32 initTimeOut, acceptTimeOut, outTime = GSS_C_INDEFINITE;
+ gss_OID_set_desc default_OID_set;
+ gss_OID_set mechs;
+ gss_OID_desc default_OID;
+ gss_mechanism mech;
+ int i;
+ gss_union_cred_t creds;
+
+ /* start by checking parameters */
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (desired_name == GSS_C_NO_NAME)
+ return (GSS_S_BAD_NAME);
+
+ if (output_cred_handle == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED);
+
+ *output_cred_handle = GSS_C_NO_CREDENTIAL;
+
+ /* Set output parameters to NULL for now */
+ if (actual_mechs != NULL)
+ *actual_mechs = GSS_C_NULL_OID_SET;
+
+ if (time_rec)
+ *time_rec = 0;
+
+ /*
+ * if desired_mechs equals GSS_C_NULL_OID_SET, then pick an
+ * appropriate default. We use the first mechanism in the
+ * mechansim list as the default. This set is created with
+ * statics thus needs not be freed
+ */
+ if (desired_mechs == GSS_C_NULL_OID_SET) {
+ mech = __gss_get_mechanism(GSS_C_NULL_OID);
+ if (mech == NULL)
+ return (GSS_S_BAD_MECH);
+
+ 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;
+ } else
+ mechs = desired_mechs;
+
+ if (mechs->count == 0)
+ return (GSS_S_BAD_MECH);
+
+ /* allocate the output credential structure */
+ creds = (gss_union_cred_t)malloc(sizeof (gss_union_cred_desc));
+ if (creds == NULL)
+ return (GSS_S_FAILURE);
+
+ /* initialize to 0s */
+ (void) memset(creds, 0, sizeof (gss_union_cred_desc));
+
+ /* for each requested mech attempt to obtain a credential */
+ for (i = 0; i < mechs->count; i++) {
+ major = gss_add_cred_with_password(minor_status,
+ (gss_cred_id_t)creds,
+ desired_name,
+ &mechs->elements[i],
+ password,
+ cred_usage, time_req, time_req, NULL,
+ NULL, &initTimeOut, &acceptTimeOut);
+ if (major == GSS_S_COMPLETE) {
+ /* update the credential's time */
+ if (cred_usage == GSS_C_ACCEPT) {
+ if (outTime > acceptTimeOut)
+ outTime = acceptTimeOut;
+ } else if (cred_usage == GSS_C_INITIATE) {
+ if (outTime > initTimeOut)
+ outTime = initTimeOut;
+ } else {
+ /*
+ * time_rec is the lesser of the
+ * init/accept times
+ */
+ if (initTimeOut > acceptTimeOut)
+ outTime = (outTime > acceptTimeOut) ?
+ acceptTimeOut : outTime;
+ else
+ outTime = (outTime > initTimeOut) ?
+ initTimeOut : outTime;
+ }
+ }
+ } /* for */
+
+ /* ensure that we have at least one credential element */
+ if (creds->count < 1) {
+ free(creds);
+ return (major);
+ }
+
+ /*
+ * fill in output parameters
+ * setup the actual mechs output parameter
+ */
+ if (actual_mechs != NULL) {
+ if ((*actual_mechs = create_actual_mechs(creds->mechs_array,
+ creds->count)) == NULL) {
+ (void) gss_release_cred(minor_status,
+ (gss_cred_id_t *)&creds);
+ *minor_status = 0;
+ return (GSS_S_FAILURE);
+ }
+ }
+
+ if (time_rec)
+ *time_rec = outTime;
+
+
+ *output_cred_handle = (gss_cred_id_t)creds;
+ return (GSS_S_COMPLETE);
+}
+
+/* V2 INTERFACE */
+OM_uint32
+gss_add_cred_with_password(minor_status, input_cred_handle,
+ desired_name, desired_mech, password,
+ cred_usage, initiator_time_req,
+ acceptor_time_req, output_cred_handle,
+ actual_mechs, initiator_time_rec,
+ acceptor_time_rec)
+ OM_uint32 *minor_status;
+ const gss_cred_id_t input_cred_handle;
+ const gss_name_t desired_name;
+ const gss_OID desired_mech;
+ const gss_buffer_t password;
+ 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, time_req, time_rec, temp_minor_status;
+ gss_mechanism mech;
+ gss_mechanism_ext mech_ext;
+ gss_union_name_t union_name = NULL;
+ gss_union_cred_t union_cred, new_union_cred;
+ gss_name_t internal_name = GSS_C_NO_NAME;
+ gss_name_t allocated_name = GSS_C_NO_NAME;
+ gss_cred_id_t cred = NULL;
+ gss_OID new_mechs_array = NULL;
+ gss_cred_id_t *new_cred_array = NULL;
+
+ /* check input parameters */
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (input_cred_handle == GSS_C_NO_CREDENTIAL &&
+ output_cred_handle == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CRED);
+
+ if (desired_name == GSS_C_NO_NAME)
+ return (GSS_S_BAD_NAME);
+ union_name = (gss_union_name_t)desired_name;
+
+ if (output_cred_handle != NULL)
+ *output_cred_handle = GSS_C_NO_CREDENTIAL;
+
+ if (actual_mechs != NULL)
+ *actual_mechs = NULL;
+
+ if (acceptor_time_rec != NULL)
+ *acceptor_time_rec = 0;
+
+ if (initiator_time_rec != NULL)
+ *initiator_time_rec = 0;
+
+ if ((mech = __gss_get_mechanism(desired_mech)) == NULL)
+ return (GSS_S_BAD_MECH);
+
+ if ((mech_ext = __gss_get_mechanism_ext(desired_mech)) == NULL ||
+ mech_ext->gss_acquire_cred_with_password == NULL)
+ return (GSS_S_UNAVAILABLE);
+
+ if (input_cred_handle == GSS_C_NO_CREDENTIAL) {
+ union_cred = malloc(sizeof (gss_union_cred_desc));
+ if (union_cred == NULL)
+ return (GSS_S_FAILURE);
+
+ (void) memset(union_cred, 0, sizeof (gss_union_cred_desc));
+
+ } else {
+ union_cred = (gss_union_cred_t)input_cred_handle;
+ if (__gss_get_mechanism_cred(union_cred, desired_mech) !=
+ GSS_C_NO_CREDENTIAL)
+ return (GSS_S_DUPLICATE_ELEMENT);
+ }
+
+ /* May need to create an MN */
+ if (union_name->mech_type &&
+ g_OID_equal(union_name->mech_type,
+ &mech->mech_type))
+ internal_name = union_name->mech_name;
+ else {
+ if (__gss_import_internal_name(minor_status,
+ &mech->mech_type, union_name,
+ &allocated_name) != GSS_S_COMPLETE)
+ return (GSS_S_BAD_NAME);
+ internal_name = allocated_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;
+
+ status = mech_ext->gss_acquire_cred_with_password(mech->context,
+ minor_status, internal_name, password, time_req,
+ GSS_C_NULL_OID_SET, cred_usage, &cred, NULL,
+ &time_rec);
+
+ if (status != GSS_S_COMPLETE)
+ goto errout;
+
+ /* May need to set credential auxinfo strucutre */
+ if (union_cred->auxinfo.creation_time == 0) {
+ union_cred->auxinfo.creation_time = time(NULL);
+ union_cred->auxinfo.time_rec = time_rec;
+ union_cred->auxinfo.cred_usage = cred_usage;
+
+ if ((status = mech->gss_display_name(mech->context,
+ &temp_minor_status, internal_name,
+ &union_cred->auxinfo.name,
+ &union_cred->auxinfo.name_type)) !=
+ GSS_S_COMPLETE)
+ goto errout;
+ }
+
+ /* Now add the new credential elements */
+ 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) {
+ 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 and the credential array
+ */
+ (void) memcpy(new_mechs_array, union_cred->mechs_array,
+ sizeof (gss_OID_desc) * union_cred->count);
+ (void) memcpy(new_cred_array, union_cred->cred_array,
+ sizeof (gss_cred_id_t) * union_cred->count);
+
+ new_cred_array[union_cred->count] = cred;
+ if ((new_mechs_array[union_cred->count].elements =
+ malloc(mech->mech_type.length)) == NULL)
+ goto errout;
+
+ g_OID_copy(&new_mechs_array[union_cred->count],
+ &mech->mech_type);
+
+ if (actual_mechs) {
+ *actual_mechs = create_actual_mechs(new_mechs_array,
+ union_cred->count + 1);
+ if (*actual_mechs == NULL) {
+ free(new_mechs_array[union_cred->count].elements);
+ goto errout;
+ }
+ }
+
+ 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) {
+ free(new_mechs_array[union_cred->count].elements);
+ goto errout;
+ }
+ *new_union_cred = *union_cred;
+ *output_cred_handle = (gss_cred_id_t)new_union_cred;
+ }
+
+ new_union_cred->mechs_array = new_mechs_array;
+ new_union_cred->cred_array = new_cred_array;
+ new_union_cred->count++;
+
+ /* We're done with the internal name. Free it if we allocated it. */
+
+ if (allocated_name)
+ (void) __gss_release_internal_name(&temp_minor_status,
+ &mech->mech_type,
+ &allocated_name);
+
+ return (GSS_S_COMPLETE);
+
+errout:
+ if (new_mechs_array)
+ free(new_mechs_array);
+ if (new_cred_array)
+ free(new_cred_array);
+
+ if (cred != NULL && mech->gss_release_cred)
+ mech->gss_release_cred(mech->context,
+ &temp_minor_status, &cred);
+
+ if (allocated_name)
+ (void) __gss_release_internal_name(&temp_minor_status,
+ &mech->mech_type,
+ &allocated_name);
+
+ if (input_cred_handle == GSS_C_NO_CREDENTIAL && union_cred) {
+ if (union_cred->auxinfo.name.value)
+ free(union_cred->auxinfo.name.value);
+ free(union_cred);
+ }
+
+ return (status);
+}
diff --git a/usr/src/lib/libgss/g_canon_name.c b/usr/src/lib/libgss/g_canon_name.c
new file mode 100644
index 0000000000..60debfa16e
--- /dev/null
+++ b/usr/src/lib/libgss/g_canon_name.c
@@ -0,0 +1,176 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * routine gss_canonicalize_name
+ *
+ * This routine is used to produce a mechanism specific
+ * representation of name that has been previously
+ * imported with gss_import_name. The routine uses the mechanism
+ * specific implementation of gss_import_name to implement this
+ * function.
+ *
+ * We allow a NULL output_name, in which case we modify the
+ * input_name to include the mechanism specific name.
+ */
+
+#include <mechglueP.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+OM_uint32
+gss_canonicalize_name(minor_status,
+ input_name,
+ mech_type,
+ output_name)
+OM_uint32 *minor_status;
+const gss_name_t input_name;
+const gss_OID mech_type;
+gss_name_t *output_name;
+{
+ gss_union_name_t in_union, out_union = NULL, dest_union = NULL;
+ OM_uint32 major_status = GSS_S_FAILURE;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *minor_status = 0;
+
+ if (output_name)
+ *output_name = 0;
+
+ /* check the input parameters */
+ if (input_name == NULL || mech_type == GSS_C_NULL_OID)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ in_union = (gss_union_name_t)input_name;
+ /*
+ * If the caller wants to reuse the name, and the name has already
+ * been converted, then there is nothing for us to do.
+ */
+ if (!output_name && in_union->mech_type &&
+ g_OID_equal(in_union->mech_type, mech_type))
+ return (GSS_S_COMPLETE);
+
+ /* ok, then we need to do something - start by creating data struct */
+ if (output_name) {
+ out_union =
+ (gss_union_name_t)malloc(sizeof (gss_union_name_desc));
+ if (!out_union)
+ goto allocation_failure;
+
+ out_union->mech_type = 0;
+ out_union->mech_name = 0;
+ out_union->name_type = 0;
+ out_union->external_name = 0;
+
+ /* Allocate the buffer for the user specified representation */
+ if (__gss_create_copy_buffer(in_union->external_name,
+ &out_union->external_name, 1))
+ goto allocation_failure;
+
+ if (in_union->name_type != GSS_C_NULL_OID) {
+ if ((major_status = generic_gss_copy_oid(minor_status,
+ in_union->name_type, &out_union->name_type)))
+ goto allocation_failure;
+ }
+
+ }
+
+ /*
+ * might need to delete any old mechanism names if we are
+ * reusing the buffer.
+ */
+ if (!output_name) {
+ if (in_union->mech_type) {
+ (void) __gss_release_internal_name(minor_status,
+ in_union->mech_type,
+ &in_union->mech_name);
+ (void) gss_release_oid(minor_status,
+ &in_union->mech_type);
+ in_union->mech_type = 0;
+ }
+ dest_union = in_union;
+ } else
+ dest_union = out_union;
+
+ /* now let's create the new mech name */
+ if (major_status = generic_gss_copy_oid(minor_status, mech_type,
+ &dest_union->mech_type))
+ goto allocation_failure;
+
+ if (major_status =
+ __gss_import_internal_name(minor_status, mech_type,
+ dest_union,
+ &dest_union->mech_name))
+ goto allocation_failure;
+
+ if (output_name)
+ *output_name = (gss_name_t)dest_union;
+
+ return (GSS_S_COMPLETE);
+
+allocation_failure:
+ /* do not delete the src name external name format */
+ if (output_name) {
+ if (out_union->external_name) {
+ if (out_union->external_name->value)
+ free(out_union->external_name->value);
+ free(out_union->external_name);
+ }
+ if (out_union->name_type)
+ (void) gss_release_oid(minor_status,
+ &out_union->name_type);
+
+ dest_union = out_union;
+ } else
+ dest_union = in_union;
+
+ /*
+ * delete the partially created mech specific name
+ * applies for both src and dest which ever is being used for output
+ */
+
+ if (dest_union->mech_name) {
+ (void) __gss_release_internal_name(minor_status,
+ dest_union->mech_type,
+ &dest_union->mech_name);
+ }
+
+ if (dest_union->mech_type)
+ (void) gss_release_oid(minor_status, &dest_union->mech_type);
+
+
+ if (output_name)
+ free(out_union);
+
+ return (major_status);
+} /********** gss_canonicalize_name ********/
diff --git a/usr/src/lib/libgss/g_compare_name.c b/usr/src/lib/libgss/g_compare_name.c
new file mode 100644
index 0000000000..1fefbee01f
--- /dev/null
+++ b/usr/src/lib/libgss/g_compare_name.c
@@ -0,0 +1,183 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine for gss_compare_name
+ *
+ */
+
+#include <mechglueP.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+OM_uint32
+gss_compare_name(minor_status,
+ name1,
+ name2,
+ name_equal)
+
+OM_uint32 *minor_status;
+const gss_name_t name1;
+const 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;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (name1 == 0 || name2 == 0)
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
+
+ if (name_equal == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ 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_UNAVAILABLE);
+ }
+
+ *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);
+ return (mech->gss_compare_name(mech->context, minor_status,
+ 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) {
+ /*
+ * Second case, first sub-case... one name has null
+ * name_type, the other doesn't.
+ *
+ * Not knowing a mech_type we can't import the name with
+ * null name_type so we can't compare.
+ */
+ if ((union_name1->name_type == GSS_C_NULL_OID &&
+ union_name2->name_type != GSS_C_NULL_OID) ||
+ (union_name1->name_type != GSS_C_NULL_OID &&
+ union_name2->name_type == GSS_C_NULL_OID))
+ return (GSS_S_COMPLETE);
+ /*
+ * Second case, second sub-case... both names have
+ * name_types, but they are different.
+ */
+ if ((union_name1->name_type != GSS_C_NULL_OID &&
+ union_name2->name_type != GSS_C_NULL_OID) &&
+ !g_OID_equal(union_name1->name_type,
+ union_name2->name_type))
+ return (GSS_S_COMPLETE);
+ /*
+ * Second case, third sub-case... both names have equal
+ * name_types (and both have no mech_types) so we just
+ * compare the external_names.
+ */
+ 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); /* return complete, but not equal */
+
+ major_status = mech->gss_compare_name(mech->context, minor_status,
+ union_name1->mech_name,
+ internal_name,
+ name_equal);
+ (void) __gss_release_internal_name(&temp_minor, union_name1->mech_type,
+ &internal_name);
+ return (major_status);
+}
diff --git a/usr/src/lib/libgss/g_context_time.c b/usr/src/lib/libgss/g_context_time.c
new file mode 100644
index 0000000000..07ae0860c1
--- /dev/null
+++ b/usr/src/lib/libgss/g_context_time.c
@@ -0,0 +1,81 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996,1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routines for gss_context_time
+ */
+
+#include <mechglueP.h>
+
+OM_uint32
+gss_context_time(minor_status,
+ context_handle,
+ time_rec)
+
+OM_uint32 * minor_status;
+const gss_ctx_id_t context_handle;
+OM_uint32 * time_rec;
+{
+ OM_uint32 status;
+ gss_union_ctx_id_t ctx;
+ gss_mechanism mech;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (time_rec == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ if (context_handle == GSS_C_NO_CONTEXT)
+ return (GSS_S_CALL_INACCESSIBLE_READ | 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(
+ mech->context,
+ minor_status,
+ ctx->internal_ctx_id,
+ time_rec);
+ else
+ status = GSS_S_UNAVAILABLE;
+
+ return (status);
+ }
+
+ return (GSS_S_BAD_MECH);
+}
diff --git a/usr/src/lib/libgss/g_delete_sec_context.c b/usr/src/lib/libgss/g_delete_sec_context.c
new file mode 100644
index 0000000000..bb089c08cf
--- /dev/null
+++ b/usr/src/lib/libgss/g_delete_sec_context.c
@@ -0,0 +1,88 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996,1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine for gss_delete_sec_context
+ */
+
+#include <mechglueP.h>
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+OM_uint32
+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;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ /* if the context_handle is Null, return NO_CONTEXT error */
+ if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT)
+ return (GSS_S_CALL_INACCESSIBLE_READ | 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(mech->context,
+ minor_status,
+ &ctx->internal_ctx_id,
+ output_token);
+ else
+ status = GSS_S_UNAVAILABLE;
+
+ /* 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_BAD_MECH);
+}
diff --git a/usr/src/lib/libgss/g_dsp_name.c b/usr/src/lib/libgss/g_dsp_name.c
new file mode 100644
index 0000000000..b027ff466f
--- /dev/null
+++ b/usr/src/lib/libgss/g_dsp_name.c
@@ -0,0 +1,112 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine for gss_display_name()
+ *
+ */
+
+#include <mechglueP.h>
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+OM_uint32
+gss_display_name(minor_status,
+ input_name,
+ output_name_buffer,
+ output_name_type)
+
+OM_uint32 * minor_status;
+const 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 (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (input_name == 0)
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
+
+ if (output_name_buffer == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ if (output_name_type)
+ *output_name_type = NULL;
+
+ 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 &&
+ union_name->name_type != GSS_C_NULL_OID) {
+ major_status = generic_gss_copy_oid(minor_status,
+ union_name->name_type,
+ output_name_type);
+ if (major_status != GSS_S_COMPLETE)
+ return (major_status);
+ }
+
+ if ((output_name_buffer->value =
+ malloc(union_name->external_name->length + 1)) == NULL) {
+ if (output_name_type && *output_name_type != GSS_C_NULL_OID) {
+ (void) generic_gss_release_oid(minor_status,
+ output_name_type);
+ *output_name_type = NULL;
+ }
+ return (GSS_S_FAILURE);
+ }
+ output_name_buffer->length = union_name->external_name->length;
+ (void) memcpy(output_name_buffer->value,
+ union_name->external_name->value,
+ union_name->external_name->length);
+ ((char *)output_name_buffer->value)[output_name_buffer->length] = '\0';
+
+ return (GSS_S_COMPLETE);
+}
diff --git a/usr/src/lib/libgss/g_dsp_status.c b/usr/src/lib/libgss/g_dsp_status.c
new file mode 100644
index 0000000000..8ea9afacac
--- /dev/null
+++ b/usr/src/lib/libgss/g_dsp_status.c
@@ -0,0 +1,367 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine gss_display_status
+ *
+ */
+
+#include <mechglueP.h>
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <libintl.h>
+#include <errno.h>
+
+#ifndef TEXT_DOMAIN
+#error TEXT_DOMAIN not defined
+#endif
+
+/* local function */
+static OM_uint32 displayMajor(OM_uint32, OM_uint32 *, gss_buffer_t);
+
+
+OM_uint32
+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;
+const gss_OID req_mech_type;
+OM_uint32 *message_context;
+gss_buffer_t status_string;
+{
+ gss_OID mech_type = (gss_OID) req_mech_type;
+ gss_mechanism mech;
+
+ /* check the input parameters */
+ if (!minor_status)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *minor_status = 0;
+
+ if (!message_context || status_string == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ status_string->length = 0;
+ status_string->value = NULL;
+
+ /* we handle major status codes, and the mechs do the minor */
+ if (status_type == GSS_C_GSS_CODE)
+ return (displayMajor(status_value, message_context,
+ status_string));
+
+ /*
+ * must be the minor status - let mechs do the work
+ * select the appropriate underlying mechanism routine and
+ * call it.
+ */
+ mech = __gss_get_mechanism(mech_type);
+
+ if (mech && mech->gss_display_status) {
+ if (mech_type == GSS_C_NULL_OID)
+ mech_type = &mech->mech_type;
+
+ return (mech->gss_display_status(mech->context, minor_status,
+ status_value, status_type, mech_type,
+ message_context, status_string));
+ }
+
+ if (!mech)
+ return (GSS_S_BAD_MECH);
+
+ return (GSS_S_UNAVAILABLE);
+} /* gss_display_status */
+
+
+/*
+ * function to map the major error codes
+ * it uses case statements so that the strings could be wrapped by gettext
+ * msgCtxt is interpreted as:
+ * 0 - first call
+ * 1 - routine error
+ * >= 2 - the supplementary error code bit shifted by 1
+ */
+static OM_uint32
+displayMajor(status, msgCtxt, outStr)
+OM_uint32 status;
+OM_uint32 *msgCtxt;
+gss_buffer_t outStr;
+{
+ OM_uint32 oneVal, mask = 0x1, currErr;
+ char *errStr = NULL;
+ int i, haveErr = 0;
+
+ /* take care of the success value first */
+ if (status == GSS_S_COMPLETE)
+ errStr = dgettext(TEXT_DOMAIN,
+ "The routine completed successfully");
+ else if (*msgCtxt == 0 && (oneVal = GSS_CALLING_ERROR(status))) {
+ switch (oneVal) {
+ case GSS_S_CALL_INACCESSIBLE_READ:
+ errStr = dgettext(TEXT_DOMAIN,
+ "A required input parameter"
+ " could not be read");
+ break;
+
+ case GSS_S_CALL_INACCESSIBLE_WRITE:
+ errStr = dgettext(TEXT_DOMAIN,
+ "A required output parameter"
+ " could not be written");
+ break;
+
+ case GSS_S_CALL_BAD_STRUCTURE:
+ errStr = dgettext(TEXT_DOMAIN,
+ "A parameter was malformed");
+ break;
+
+ default:
+ errStr = dgettext(TEXT_DOMAIN,
+ "An invalid status code was supplied");
+ break;
+ }
+
+ /* we now need to determine new value of msgCtxt */
+ if (GSS_ROUTINE_ERROR(status))
+ *msgCtxt = 1;
+ else if ((oneVal = GSS_SUPPLEMENTARY_INFO(status)) != 0)
+ *msgCtxt = (OM_uint32)(oneVal << 1);
+ else
+ *msgCtxt = 0;
+
+ } else if ((*msgCtxt == 0 || *msgCtxt == 1) &&
+ (oneVal = GSS_ROUTINE_ERROR(status))) {
+ switch (oneVal) {
+ case GSS_S_BAD_MECH:
+ errStr = dgettext(TEXT_DOMAIN,
+ "An unsupported mechanism"
+ " was requested");
+ break;
+
+ case GSS_S_BAD_NAME:
+ errStr = dgettext(TEXT_DOMAIN,
+ "An invalid name was supplied");
+ break;
+
+ case GSS_S_BAD_NAMETYPE:
+ errStr = dgettext(TEXT_DOMAIN,
+ "A supplied name was of an"
+ " unsupported type");
+ break;
+
+ case GSS_S_BAD_BINDINGS:
+ errStr = dgettext(TEXT_DOMAIN,
+ "Incorrect channel bindings"
+ " were supplied");
+ break;
+
+ case GSS_S_BAD_SIG: /* same as GSS_S_BAD_MIC: */
+ errStr = dgettext(TEXT_DOMAIN,
+ "A token had an invalid Message"
+ " Integrity Check (MIC)");
+ break;
+
+ case GSS_S_NO_CRED:
+ errStr = dgettext(TEXT_DOMAIN,
+ "No credentials were supplied, or the"
+ " credentials were unavailable or"
+ " inaccessible");
+ break;
+
+ case GSS_S_NO_CONTEXT:
+ errStr = dgettext(TEXT_DOMAIN,
+ "No context has been established");
+ break;
+
+ case GSS_S_DEFECTIVE_TOKEN:
+ errStr = dgettext(TEXT_DOMAIN,
+ "Invalid token was supplied");
+ break;
+
+ case GSS_S_DEFECTIVE_CREDENTIAL:
+ errStr = dgettext(TEXT_DOMAIN,
+ "Invalid credential was supplied");
+ break;
+
+ case GSS_S_CREDENTIALS_EXPIRED:
+ errStr = dgettext(TEXT_DOMAIN,
+ "The referenced credential has"
+ " expired");
+ break;
+
+ case GSS_S_CONTEXT_EXPIRED:
+ errStr = dgettext(TEXT_DOMAIN,
+ "The referenced context has expired");
+ break;
+
+ case GSS_S_FAILURE:
+ errStr = dgettext(TEXT_DOMAIN,
+ "Unspecified GSS failure. Minor code"
+ " may provide more information");
+ break;
+
+ case GSS_S_BAD_QOP:
+ errStr = dgettext(TEXT_DOMAIN,
+ "The quality-of-protection (QOP) "
+ "requested could not be provided");
+ break;
+
+ case GSS_S_UNAUTHORIZED:
+ errStr = dgettext(TEXT_DOMAIN,
+ "The operation is forbidden by local"
+ " security policy");
+ break;
+
+ case GSS_S_UNAVAILABLE:
+ errStr = dgettext(TEXT_DOMAIN,
+ "The operation or option is not"
+ " available or unsupported");
+ break;
+
+ case GSS_S_DUPLICATE_ELEMENT:
+ errStr = dgettext(TEXT_DOMAIN,
+ "The requested credential element"
+ " already exists");
+ break;
+
+ case GSS_S_NAME_NOT_MN:
+ errStr = dgettext(TEXT_DOMAIN,
+ "The provided name was not mechanism"
+ " specific (MN)");
+ break;
+
+ case GSS_S_BAD_STATUS:
+ default:
+ errStr = dgettext(TEXT_DOMAIN,
+ "An invalid status code was supplied");
+ }
+
+ /* we must determine if the caller should call us again */
+ if ((oneVal = GSS_SUPPLEMENTARY_INFO(status)) != 0)
+ *msgCtxt = (OM_uint32)(oneVal << 1);
+ else
+ *msgCtxt = 0;
+
+ } else if ((*msgCtxt == 0 || *msgCtxt >= 2) &&
+ (oneVal = GSS_SUPPLEMENTARY_INFO(status))) {
+ /*
+ * if msgCtxt is not 0, then it should encode
+ * the supplementary error code we should be printing
+ */
+ if (*msgCtxt >= 2)
+ oneVal = (OM_uint32) (*msgCtxt) >> 1;
+ else
+ oneVal = GSS_SUPPLEMENTARY_INFO(status);
+
+ /* we display the errors LSB first */
+ for (i = 0; i < 16; i++) {
+ if (oneVal & mask) {
+ haveErr = 1;
+ break;
+ }
+ mask <<= 1;
+ }
+
+ /* isolate the bit or if not found set to illegal value */
+ if (haveErr)
+ currErr = oneVal & mask;
+ else
+ currErr = 1 << 17; /* illegal value */
+
+ switch (currErr) {
+ case GSS_S_CONTINUE_NEEDED:
+ errStr = dgettext(TEXT_DOMAIN,
+ "The routine must be called again to"
+ " complete its function");
+ break;
+
+ case GSS_S_DUPLICATE_TOKEN:
+ errStr = dgettext(TEXT_DOMAIN,
+ "The token was a duplicate of an"
+ " earlier token");
+ break;
+
+ case GSS_S_OLD_TOKEN:
+ errStr = dgettext(TEXT_DOMAIN,
+ "The token's validity period"
+ " has expired");
+ break;
+
+ case GSS_S_UNSEQ_TOKEN:
+ errStr = dgettext(TEXT_DOMAIN,
+ "A later token has already been"
+ " processed");
+ break;
+
+ case GSS_S_GAP_TOKEN:
+ errStr = dgettext(TEXT_DOMAIN,
+ "An expected per-message token was"
+ " not received");
+ break;
+
+ default:
+ errStr = dgettext(TEXT_DOMAIN,
+ "An invalid status code was supplied");
+ }
+
+ /*
+ * we must check if there is any other supplementary errors
+ * if found, then turn off current bit, and store next value
+ * in msgCtxt shifted by 1 bit
+ */
+ if (!haveErr)
+ *msgCtxt = 0;
+ else if (GSS_SUPPLEMENTARY_INFO(oneVal) ^ mask)
+ *msgCtxt = (OM_uint32)
+ ((GSS_SUPPLEMENTARY_INFO(oneVal) ^ mask) << 1);
+ else
+ *msgCtxt = 0;
+ }
+
+ if (errStr == NULL)
+ errStr = dgettext(TEXT_DOMAIN,
+ "An invalid status code was supplied");
+
+ /* now copy the status code and return to caller */
+ outStr->length = strlen(errStr);
+ outStr->value = malloc((size_t)outStr->length+1);
+ if (outStr->value == NULL) {
+ outStr->length = 0;
+ return (GSS_S_FAILURE);
+ }
+
+ (void) strcpy((char *)outStr->value, errStr);
+ return (GSS_S_COMPLETE);
+} /* displayMajor */
diff --git a/usr/src/lib/libgss/g_dup_name.c b/usr/src/lib/libgss/g_dup_name.c
new file mode 100644
index 0000000000..29079d22d0
--- /dev/null
+++ b/usr/src/lib/libgss/g_dup_name.c
@@ -0,0 +1,139 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * routine gss_duplicate_name
+ *
+ * This routine does not rely on mechanism implementation of this
+ * name, but instead uses mechanism specific gss_import_name routine.
+ */
+
+#include <mechglueP.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+OM_uint32
+gss_duplicate_name(minor_status,
+ src_name,
+ dest_name)
+OM_uint32 *minor_status;
+const gss_name_t src_name;
+gss_name_t *dest_name;
+{
+ gss_union_name_t src_union, dest_union;
+ OM_uint32 major_status = GSS_S_FAILURE;
+
+
+ if (!minor_status)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *minor_status = 0;
+
+ /* if output_name is NULL, simply return */
+ if (dest_name == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_BAD_NAME);
+
+ *dest_name = 0;
+
+ if (src_name == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ src_union = (gss_union_name_t)src_name;
+
+ /*
+ * First create the union name struct that will hold the external
+ * name and the name type.
+ */
+ dest_union = (gss_union_name_t)malloc(sizeof (gss_union_name_desc));
+ if (!dest_union)
+ goto allocation_failure;
+
+ dest_union->mech_type = 0;
+ dest_union->mech_name = 0;
+ dest_union->name_type = 0;
+ dest_union->external_name = 0;
+
+ /* Now copy the external representaion */
+ if (__gss_create_copy_buffer(src_union->external_name,
+ &dest_union->external_name, 0))
+ goto allocation_failure;
+
+ if (src_union->name_type != GSS_C_NULL_OID) {
+ major_status = generic_gss_copy_oid(minor_status,
+ src_union->name_type,
+ &dest_union->name_type);
+ if (major_status != GSS_S_COMPLETE)
+ goto allocation_failure;
+ }
+
+ /*
+ * See if source name is mechanim specific, if so then need to import it
+ */
+ if (src_union->mech_type) {
+ major_status = generic_gss_copy_oid(minor_status,
+ src_union->mech_type,
+ &dest_union->mech_type);
+ if (major_status != GSS_S_COMPLETE)
+ goto allocation_failure;
+
+ major_status = __gss_import_internal_name(minor_status,
+ dest_union->mech_type,
+ dest_union,
+ &dest_union->mech_name);
+ if (major_status != GSS_S_COMPLETE)
+ goto allocation_failure;
+ }
+
+
+ *dest_name = (gss_name_t)dest_union;
+ return (GSS_S_COMPLETE);
+
+allocation_failure:
+ if (dest_union) {
+ if (dest_union->external_name) {
+ if (dest_union->external_name->value)
+ free(dest_union->external_name->value);
+ free(dest_union->external_name);
+ }
+ if (dest_union->name_type)
+ (void) generic_gss_release_oid(minor_status,
+ &dest_union->name_type);
+ if (dest_union->mech_name)
+ (void) __gss_release_internal_name(minor_status,
+ dest_union->mech_type,
+ &dest_union->mech_name);
+ if (dest_union->mech_type)
+ (void) generic_gss_release_oid(minor_status,
+ &dest_union->mech_type);
+ free(dest_union);
+ }
+ return (major_status);
+} /* gss_duplicate_name */
diff --git a/usr/src/lib/libgss/g_exp_sec_context.c b/usr/src/lib/libgss/g_exp_sec_context.c
new file mode 100644
index 0000000000..954ac9dec1
--- /dev/null
+++ b/usr/src/lib/libgss/g_exp_sec_context.c
@@ -0,0 +1,113 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine for gss_export_sec_context
+ */
+
+#include <mechglueP.h>
+#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+OM_uint32
+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;
+ OM_uint32 length;
+ gss_union_ctx_id_t ctx;
+ gss_mechanism mech;
+ gss_buffer_desc token;
+ char *buf;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT)
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+ if (interprocess_token == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ /*
+ * 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_UNAVAILABLE);
+
+ status = mech->gss_export_sec_context(mech->context, minor_status,
+ &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);
+ 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);
+ (void) memcpy(buf+4, ctx->mech_type->elements,
+ (size_t)ctx->mech_type->length);
+ (void) 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/usr/src/lib/libgss/g_export_name.c b/usr/src/lib/libgss/g_export_name.c
new file mode 100644
index 0000000000..2b81c39f9c
--- /dev/null
+++ b/usr/src/lib/libgss/g_export_name.c
@@ -0,0 +1,76 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996,1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine gss_export_name
+ *
+ * Will either call the mechanism defined gss_export_name, or if one is
+ * not defined will call a generic_gss_export_name routine.
+ */
+
+#include <mechglueP.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+OM_uint32
+gss_export_name(minor_status,
+ input_name,
+ exported_name)
+OM_uint32 * minor_status;
+const gss_name_t input_name;
+gss_buffer_t exported_name;
+{
+ gss_union_name_t union_name;
+
+
+ if (minor_status)
+ *minor_status = 0;
+
+ /* check out parameter */
+ if (!exported_name)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ exported_name->value = NULL;
+ exported_name->length = 0;
+
+ /* check input parameter */
+ if (!input_name)
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
+
+ union_name = (gss_union_name_t)input_name;
+
+ /* the name must be in mechanism specific format */
+ if (!union_name->mech_type)
+ return (GSS_S_NAME_NOT_MN);
+
+ return __gss_export_internal_name(minor_status, union_name->mech_type,
+ union_name->mech_name, exported_name);
+}
diff --git a/usr/src/lib/libgss/g_glue.c b/usr/src/lib/libgss/g_glue.c
new file mode 100644
index 0000000000..f01c1d29c7
--- /dev/null
+++ b/usr/src/lib/libgss/g_glue.c
@@ -0,0 +1,586 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <mechglueP.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <errno.h>
+
+#define MSO_BIT (8*(sizeof (int) - 1)) /* Most significant octet bit */
+
+/*
+ * This file contains the support routines for the glue layer.
+ */
+
+/*
+ * get_der_length: Givin a pointer to a buffer that contains a DER encoded
+ * length, decode the length updating the buffer to point to the character
+ * after the DER encoding. The parameter bytes will point to the number of
+ * bytes that made up the DER encoding of the length originally pointed to
+ * by the buffer. Note we return -1 on error.
+ */
+int
+get_der_length(unsigned char **buf, unsigned int buf_len, unsigned int *bytes)
+{
+ /* p points to the beginning of the buffer */
+ unsigned char *p = *buf;
+ int length, new_length;
+ int octets;
+
+ if (buf_len < 1)
+ return (-1);
+
+ /* We should have at least one byte */
+ *bytes = 1;
+
+ /*
+ * If the High order bit is not set then the length is just the value
+ * of *p.
+ */
+ if (*p < 128) {
+ *buf = p+1; /* Advance the buffer */
+ return (*p); /* return the length */
+ }
+
+ /*
+ * if the High order bit is set, then the low order bits represent
+ * the number of bytes that contain the DER encoding of the length.
+ */
+
+ octets = *p++ & 0x7f;
+ *bytes += octets;
+
+ /* See if the supplied buffer contains enough bytes for the length. */
+ if (octets > buf_len - 1)
+ return (-1);
+
+ /*
+ * Calculate a multibyte length. The length is encoded as an
+ * unsigned integer base 256.
+ */
+ for (length = 0; octets; octets--) {
+ new_length = (length << 8) + *p++;
+ if (new_length < length) /* overflow */
+ return (-1);
+ length = new_length;
+ }
+
+ *buf = p; /* Advance the buffer */
+
+ return (length);
+}
+
+/*
+ * der_length_size: Return the number of bytes to encode a given length.
+ */
+unsigned int
+der_length_size(unsigned int len)
+{
+ int i;
+
+ if (len < 128)
+ return (1);
+
+ for (i = 0; len; i++) {
+ len >>= 8;
+ }
+
+ return (i+1);
+}
+
+/*
+ * put_der_length: Encode the supplied length into the buffer pointed to
+ * by buf. max_length represents the maximum length of the buffer pointed
+ * to by buff. We will advance buf to point to the character after the newly
+ * DER encoded length. We return 0 on success or -l it the length cannot
+ * be encoded in max_len characters.
+ */
+int
+put_der_length(unsigned length, unsigned char **buf, unsigned int max_len)
+{
+ unsigned char *s = *buf, *p;
+ unsigned int buf_len = 0;
+ int i, first;
+
+ /* Oops */
+ if (buf == 0 || max_len < 1)
+ return (-1);
+
+ /* Single byte is the length */
+ if (length < 128) {
+ *s++ = length;
+ *buf = s;
+ return (0);
+ }
+
+ /* First byte contains the number of octets */
+ p = s + 1;
+
+ /* Running total of the DER encoding length */
+ buf_len = 0;
+
+ /*
+ * Encode MSB first. We do the encoding by setting a shift
+ * factor to MSO_BIT (24 for 32 bit words) and then shifting the length
+ * by the factor. We then encode the resulting low order byte.
+ * We subtract 8 from the shift factor and repeat to ecnode the next
+ * byte. We stop when the shift factor is zero or we've run out of
+ * buffer to encode into.
+ */
+ first = 0;
+ for (i = MSO_BIT; i >= 0 && buf_len <= max_len; i -= 8) {
+ unsigned int v;
+ v = (length >> i) & 0xff;
+ if ((v) || first) {
+ buf_len += 1;
+ *p++ = v;
+ first = 1;
+ }
+ }
+ if (i >= 0) /* buffer overflow */
+ return (-1);
+
+ /*
+ * We go back now and set the first byte to be the length with
+ * the high order bit set.
+ */
+ *s = buf_len | 0x80;
+ *buf = p;
+
+ return (0);
+}
+
+
+/*
+ * glue routine for get_mech_type
+ *
+ */
+OM_uint32
+__gss_get_mech_type(OID, token)
+ gss_OID OID;
+ const 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 (OID == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ if ((token == NULL) || (token->value == 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++;
+
+ /* check if token length is null */
+ if (length == 0)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ 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
+ */
+OM_uint32 __gss_import_internal_name(minor_status, mech_type, union_name,
+ internal_name)
+OM_uint32 *minor_status;
+const 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(
+ mech->context,
+ minor_status,
+ union_name->external_name,
+ union_name->name_type,
+ internal_name);
+ else
+ status = GSS_S_UNAVAILABLE;
+
+ return (status);
+ }
+
+ return (GSS_S_BAD_MECH);
+}
+
+
+OM_uint32 __gss_export_internal_name(minor_status, mech_type,
+ internal_name, name_buf)
+OM_uint32 *minor_status;
+const gss_OID mech_type;
+const gss_name_t internal_name;
+gss_buffer_t name_buf;
+{
+ OM_uint32 status;
+ gss_mechanism mech;
+ gss_buffer_desc dispName;
+ gss_OID nameOid;
+ unsigned char *buf = NULL;
+ const unsigned char tokId[] = "\x04\x01";
+ const int tokIdLen = 2;
+ const int mechOidLenLen = 2, mechOidTagLen = 1, nameLenLen = 4;
+ int mechOidDERLen = 0;
+ int mechOidLen = 0;
+
+ mech = __gss_get_mechanism(mech_type);
+ if (!mech)
+ return (GSS_S_BAD_MECH);
+
+ if (mech->gss_export_name)
+ return (mech->gss_export_name(mech->context,
+ minor_status,
+ internal_name,
+ name_buf));
+
+ /*
+ * if we are here it is because the mechanism does not provide
+ * a gss_export_name so we will use our implementation. We
+ * do required that the mechanism define a gss_display_name.
+ */
+ if (!mech->gss_display_name)
+ return (GSS_S_UNAVAILABLE);
+
+ /*
+ * NOTE: RFC2743 (section 3.2) governs the format of the outer
+ * wrapper of exported names; the mechanisms' specs govern
+ * the format of the inner portion of the exported name
+ * and, for some (e.g., RFC1964, the Kerberos V mech), a
+ * generic default as implemented here will do.
+ *
+ * The outer wrapper of an exported MN is: 2-octet tok Id
+ * (0x0401) + 2-octet network-byte order mech OID length + mech
+ * oid (in DER format, including DER tag and DER length) +
+ * 4-octet network-byte order length of inner portion + inner
+ * portion.
+ *
+ * For the Kerberos V mechanism the inner portion of an exported
+ * MN is the display name string and ignores the name type OID
+ * altogether. And we hope this will be so for any future
+ * mechanisms also, so that factoring name export/import out of
+ * the mech and into libgss pays off.
+ */
+ if ((status = mech->gss_display_name(mech->context,
+ minor_status,
+ internal_name,
+ &dispName,
+ &nameOid))
+ != GSS_S_COMPLETE)
+ return (status);
+
+ /* determine the size of the buffer needed */
+ mechOidDERLen = der_length_size(mech_type->length);
+ name_buf->length = tokIdLen + mechOidLenLen +
+ mechOidTagLen + mechOidDERLen +
+ mech_type->length +
+ nameLenLen + dispName.length;
+ if ((name_buf->value = (void*)malloc(name_buf->length)) ==
+ (void*)NULL) {
+ name_buf->length = 0;
+ (void) gss_release_buffer(&status, &dispName);
+ return (GSS_S_FAILURE);
+ }
+
+ /* now create the name ..... */
+ buf = (unsigned char *)name_buf->value;
+ (void) memset(name_buf->value, 0, name_buf->length);
+ (void) memcpy(buf, tokId, tokIdLen);
+ buf += tokIdLen;
+
+ /* spec allows only 2 bytes for the mech oid length */
+ mechOidLen = mechOidDERLen + mechOidTagLen + mech_type->length;
+ *buf++ = (mechOidLen & 0xFF00) >> 8;
+ *buf++ = (mechOidLen & 0x00FF);
+
+ /*
+ * DER Encoding of mech OID contains OID Tag (0x06), length and
+ * mech OID value
+ */
+ *buf++ = 0x06;
+ if (put_der_length(mech_type->length, &buf,
+ (name_buf->length - tokIdLen -2)) != 0) {
+ name_buf->length = 0;
+ free(name_buf->value);
+ (void) gss_release_buffer(&status, &dispName);
+ return (GSS_S_FAILURE);
+ }
+
+ (void) memcpy(buf, mech_type->elements, mech_type->length);
+ buf += mech_type->length;
+
+ /* spec designates the next 4 bytes for the name length */
+ *buf++ = (dispName.length & 0xFF000000) >> 24;
+ *buf++ = (dispName.length & 0x00FF0000) >> 16;
+ *buf++ = (dispName.length & 0x0000FF00) >> 8;
+ *buf++ = (dispName.length & 0X000000FF);
+
+ /* for the final ingredient - add the name from gss_display_name */
+ (void) memcpy(buf, dispName.value, dispName.length);
+
+ /* release the buffer obtained from gss_display_name */
+ (void) gss_release_buffer(minor_status, &dispName);
+ return (GSS_S_COMPLETE);
+} /* __gss_export_internal_name */
+
+
+OM_uint32 __gss_display_internal_name(minor_status, mech_type, internal_name,
+ external_name, name_type)
+OM_uint32 *minor_status;
+const gss_OID mech_type;
+const 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(
+ mech->context,
+ minor_status,
+ internal_name,
+ external_name,
+ name_type);
+ else
+ status = GSS_S_UNAVAILABLE;
+
+ return (status);
+ }
+
+ return (GSS_S_BAD_MECH);
+}
+
+OM_uint32
+__gss_release_internal_name(minor_status, mech_type, internal_name)
+OM_uint32 *minor_status;
+const 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(
+ mech->context,
+ minor_status,
+ internal_name);
+ else
+ status = GSS_S_UNAVAILABLE;
+
+ 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) {
+ goto allocation_failure;
+ }
+ union_name->mech_type = 0;
+ union_name->mech_name = internal_name;
+ union_name->name_type = 0;
+ union_name->external_name = 0;
+
+ 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) {
+ goto allocation_failure;
+ }
+
+ major_status = mech->gss_display_name(mech->context, minor_status,
+ internal_name,
+ union_name->external_name,
+ &union_name->name_type);
+ if (major_status != GSS_S_COMPLETE)
+ goto allocation_failure;
+
+ *external_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)
+ (void) gss_release_oid(&tmp, &union_name->name_type);
+ if (union_name->mech_type)
+ (void) gss_release_oid(&tmp, &union_name->mech_type);
+ free(union_name);
+ }
+ /*
+ * do as the top comment says - since we are now owners of
+ * internal_name, we must clean it up
+ */
+ if (internal_name)
+ (void) __gss_release_internal_name(&tmp, &mech->mech_type,
+ &internal_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)
+ const gss_union_cred_t union_cred;
+ const gss_OID mech_type;
+{
+ int i;
+
+ if (union_cred == (gss_union_cred_t)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);
+}
+
+
+/*
+ * Routine to create and copy the gss_buffer_desc structure.
+ * Both space for the structure and the data is allocated.
+ */
+OM_uint32
+__gss_create_copy_buffer(srcBuf, destBuf, addNullChar)
+ const gss_buffer_t srcBuf;
+ gss_buffer_t *destBuf;
+ int addNullChar;
+{
+ gss_buffer_t aBuf;
+ int len;
+
+ if (destBuf == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *destBuf = 0;
+
+ aBuf = (gss_buffer_t)malloc(sizeof (gss_buffer_desc));
+ if (!aBuf)
+ return (GSS_S_FAILURE);
+
+ if (addNullChar)
+ len = srcBuf->length + 1;
+ else
+ len = srcBuf->length;
+
+ if (!(aBuf->value = (void*)malloc(len))) {
+ free(aBuf);
+ return (GSS_S_FAILURE);
+ }
+
+
+ (void) memcpy(aBuf->value, srcBuf->value, srcBuf->length);
+ aBuf->length = srcBuf->length;
+ *destBuf = aBuf;
+
+ /* optionally add a NULL character */
+ if (addNullChar)
+ ((char *)aBuf->value)[aBuf->length] = '\0';
+
+ return (GSS_S_COMPLETE);
+} /* ****** __gss_create_copy_buffer ****** */
diff --git a/usr/src/lib/libgss/g_imp_name.c b/usr/src/lib/libgss/g_imp_name.c
new file mode 100644
index 0000000000..d678d1b55c
--- /dev/null
+++ b/usr/src/lib/libgss/g_imp_name.c
@@ -0,0 +1,336 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine gss_import_name
+ *
+ */
+
+#include <mechglueP.h>
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+#include <errno.h>
+
+extern int
+get_der_length(unsigned char **, unsigned int, unsigned int *);
+
+/* local function to import GSS_C_EXPORT_NAME names */
+static OM_uint32 importExportName(OM_uint32 *, gss_union_name_t);
+
+
+OM_uint32
+gss_import_name(minor_status,
+ input_name_buffer,
+ input_name_type,
+ output_name)
+
+OM_uint32 *minor_status;
+const gss_buffer_t input_name_buffer;
+const gss_OID input_name_type;
+gss_name_t *output_name;
+{
+ gss_union_name_t union_name;
+ OM_uint32 major_status = GSS_S_FAILURE, tmp;
+
+ /* check output parameters */
+ if (!minor_status)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *minor_status = 0;
+
+ if (GSS_EMPTY_BUFFER(input_name_buffer))
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if (output_name == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *output_name = 0;
+
+ /*
+ * 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)
+ return (GSS_S_FAILURE);
+
+ union_name->mech_type = 0;
+ union_name->mech_name = 0;
+ union_name->name_type = 0;
+ union_name->external_name = 0;
+
+ /*
+ * 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. The exception to this
+ * rule is when the name of GSS_C_NT_EXPORT_NAME type. If that is
+ * the case, then we make it MN in this call.
+ */
+ major_status = __gss_create_copy_buffer(input_name_buffer,
+ &union_name->external_name, 0);
+ if (major_status != GSS_S_COMPLETE) {
+ free(union_name);
+ return (major_status);
+ }
+
+ if (input_name_type != GSS_C_NULL_OID) {
+ major_status = generic_gss_copy_oid(minor_status,
+ input_name_type,
+ &union_name->name_type);
+ if (major_status != GSS_S_COMPLETE)
+ goto allocation_failure;
+ }
+
+ /*
+ * In MIT Distribution the mechanism is determined from the nametype;
+ * This is not a good idea - first mechanism that supports a given
+ * name type is picked up; later on the caller can request a
+ * different mechanism. So we don't determine the mechanism here. Now
+ * the user level and kernel level import_name routine looks similar
+ * except the kernel routine makes a copy of the nametype structure. We
+ * do however make this an MN for names of GSS_C_NT_EXPORT_NAME type.
+ */
+ if (input_name_type != GSS_C_NULL_OID &&
+ g_OID_equal(input_name_type, GSS_C_NT_EXPORT_NAME)) {
+ major_status = importExportName(minor_status, union_name);
+ if (major_status != GSS_S_COMPLETE)
+ 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)
+ (void) generic_gss_release_oid(&tmp,
+ &union_name->name_type);
+ if (union_name->mech_name)
+ (void) __gss_release_internal_name(minor_status,
+ union_name->mech_type,
+ &union_name->mech_name);
+ if (union_name->mech_type)
+ (void) generic_gss_release_oid(&tmp,
+ &union_name->mech_type);
+ free(union_name);
+ }
+ return (major_status);
+}
+
+
+/*
+ * GSS export name constants
+ */
+static const char *expNameTokId = "\x04\x01";
+static const int expNameTokIdLen = 2;
+static const int mechOidLenLen = 2;
+static const int nameTypeLenLen = 2;
+
+static OM_uint32
+importExportName(minor, unionName)
+OM_uint32 *minor;
+gss_union_name_t unionName;
+{
+ gss_OID_desc mechOid;
+ gss_buffer_desc expName;
+ unsigned char *buf;
+ gss_mechanism mech;
+ OM_uint32 major, mechOidLen, nameLen, curLength;
+ unsigned int bytes;
+
+ expName.value = unionName->external_name->value;
+ expName.length = unionName->external_name->length;
+
+ curLength = expNameTokIdLen + mechOidLenLen;
+ if (expName.length < curLength)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ buf = (unsigned char *)expName.value;
+ if (memcmp(expNameTokId, buf, expNameTokIdLen) != 0)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ buf += expNameTokIdLen;
+
+ /* extract the mechanism oid length */
+ mechOidLen = (*buf++ << 8);
+ mechOidLen |= (*buf++);
+ curLength += mechOidLen;
+ if (expName.length < curLength)
+ return (GSS_S_DEFECTIVE_TOKEN);
+ /*
+ * The mechOid itself is encoded in DER format, OID Tag (0x06)
+ * length and the value of mech_OID
+ */
+ if (*buf++ != 0x06)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ /*
+ * mechoid Length is encoded twice; once in 2 bytes as
+ * explained in RFC2743 (under mechanism independent exported
+ * name object format) and once using DER encoding
+ *
+ * We verify both lengths.
+ */
+
+ mechOid.length = get_der_length(&buf,
+ (expName.length - curLength), &bytes);
+ mechOid.elements = (void *)buf;
+
+ /*
+ * 'bytes' is the length of the DER length, '1' is for the DER
+ * tag for OID
+ */
+ if ((bytes + mechOid.length + 1) != mechOidLen)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ buf += mechOid.length;
+ if ((mech = __gss_get_mechanism(&mechOid)) == NULL)
+ return (GSS_S_BAD_MECH);
+
+ if (mech->gss_import_name == NULL)
+ return (GSS_S_UNAVAILABLE);
+
+ /*
+ * we must now determine if we should unwrap the name ourselves
+ * or make the mechanism do it - we should only unwrap it
+ * if we create it; so if mech->gss_export_name == NULL, we must
+ * have created it.
+ */
+ if (mech->gss_export_name) {
+ if ((major = mech->gss_import_name(mech->context, minor,
+ &expName, (gss_OID)GSS_C_NT_EXPORT_NAME,
+ &unionName->mech_name)) != GSS_S_COMPLETE ||
+ (major = generic_gss_copy_oid(minor, &mechOid,
+ &unionName->mech_type)) !=
+ GSS_S_COMPLETE) {
+ return (major);
+ }
+ return (major);
+ }
+ /*
+ * we must have exported the name - so we now need to reconstruct it
+ * and call the mechanism to create it
+ *
+ * WARNING: Older versions of __gss_export_internal_name() did
+ * not export names correctly, but now it does. In
+ * order to stay compatible with existing exported
+ * names we must support names exported the broken
+ * way.
+ *
+ * Specifically, __gss_export_internal_name() used to include
+ * the name type OID in the encoding of the exported MN.
+ * Additionally, the Kerberos V mech used to make display names
+ * that included a null terminator which was counted in the
+ * display name gss_buffer_desc.
+ */
+ curLength += 4; /* 4 bytes for name len */
+ if (expName.length < curLength)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ /* next 4 bytes in the name are the name length */
+ nameLen = (*buf++) << 24;
+ nameLen |= (*buf++ << 16);
+ nameLen |= (*buf++ << 8);
+ nameLen |= (*buf++);
+
+ /*
+ * we use < here because bad code in rpcsec_gss rounds up exported
+ * name token lengths and pads with nulls, otherwise != would be
+ * appropriate
+ */
+ curLength += nameLen; /* this is the total length */
+ if (expName.length < curLength)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ /*
+ * We detect broken exported names here: they always start with
+ * a two-octet network-byte order OID length, which is always
+ * less than 256 bytes, so the first octet of the length is
+ * always '\0', which is not allowed in GSS-API display names
+ * (or never occurs in them anyways). Of course, the OID
+ * shouldn't be there, but it is. After the OID (sans DER tag
+ * and length) there's the name itself, though null-terminated;
+ * this null terminator should also not be there, but it is.
+ */
+ if (nameLen > 0 && *buf == '\0') {
+ OM_uint32 nameTypeLen;
+ /* next two bytes are the name oid */
+ if (nameLen < nameTypeLenLen)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ nameLen -= nameTypeLenLen;
+
+ nameTypeLen = (*buf++) << 8;
+ nameTypeLen |= (*buf++);
+
+ if (nameLen < nameTypeLen)
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ buf += nameTypeLen;
+ nameLen -= nameTypeLen;
+
+ /*
+ * adjust for expected null terminator that should
+ * really not be there
+ */
+ if (nameLen > 0 && *(buf + nameLen - 1) == '\0')
+ nameLen--;
+ }
+
+ /*
+ * Can a name be null? Let the mech decide.
+ *
+ * NOTE: We use GSS_C_NULL_OID as the name type when importing
+ * the unwrapped name. Presumably the exported name had,
+ * prior to being exported been obtained in such a way
+ * that it has been properly perpared ("canonicalized," in
+ * GSS-API terms) accroding to some name type; we cannot
+ * tell what that name type was now, but the name should
+ * need no further preparation other than the lowest
+ * common denominator afforded by the mech to names
+ * imported with GSS_C_NULL_OID. For the Kerberos V mech
+ * this means doing less busywork too (particularly once
+ * IDN is thrown in with Kerberos V extensions).
+ */
+ expName.length = nameLen;
+ expName.value = nameLen ? (void *)buf : NULL;
+ major = mech->gss_import_name(mech->context, minor, &expName,
+ GSS_C_NULL_OID, &unionName->mech_name);
+ if (major != GSS_S_COMPLETE)
+ return (major);
+
+ return (generic_gss_copy_oid(minor, &mechOid, &unionName->mech_type));
+} /* importExportName */
diff --git a/usr/src/lib/libgss/g_imp_sec_context.c b/usr/src/lib/libgss/g_imp_sec_context.c
new file mode 100644
index 0000000000..a34ebd1ec8
--- /dev/null
+++ b/usr/src/lib/libgss/g_imp_sec_context.c
@@ -0,0 +1,137 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine gss_export_sec_context
+ */
+
+#include <mechglueP.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+OM_uint32
+gss_import_sec_context(minor_status,
+ interprocess_token,
+ context_handle)
+
+OM_uint32 * minor_status;
+const gss_buffer_t interprocess_token;
+gss_ctx_id_t *context_handle;
+
+{
+ OM_uint32 length = 0;
+ OM_uint32 status;
+ char *p;
+ gss_union_ctx_id_t ctx;
+ gss_buffer_desc token;
+ gss_mechanism mech;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (context_handle == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CONTEXT);
+ *context_handle = GSS_C_NO_CONTEXT;
+
+ if (GSS_EMPTY_BUFFER(interprocess_token))
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_DEFECTIVE_TOKEN);
+
+ status = GSS_S_FAILURE;
+
+ ctx = (gss_union_ctx_id_t)malloc(sizeof (gss_union_ctx_id_desc));
+ if (!ctx)
+ return (GSS_S_FAILURE);
+
+ ctx->mech_type = (gss_OID) malloc(sizeof (gss_OID_desc));
+ if (!ctx->mech_type) {
+ free(ctx);
+ return (GSS_S_FAILURE);
+ }
+
+ if (interprocess_token->length >= sizeof (OM_uint32)) {
+ p = interprocess_token->value;
+ length = (OM_uint32)*p++;
+ length = (OM_uint32)(length << 8) + *p++;
+ length = (OM_uint32)(length << 8) + *p++;
+ length = (OM_uint32)(length << 8) + *p++;
+ }
+
+ if (length == 0 ||
+ length > (interprocess_token->length - sizeof (OM_uint32))) {
+ free(ctx);
+ return (GSS_S_CALL_BAD_STRUCTURE | GSS_S_DEFECTIVE_TOKEN);
+ }
+
+ ctx->mech_type->length = length;
+ ctx->mech_type->elements = malloc(length);
+ if (!ctx->mech_type->elements) {
+ goto error_out;
+ }
+ (void) memcpy(ctx->mech_type->elements, p, length);
+ p += length;
+
+ token.length = interprocess_token->length - sizeof (OM_uint32) - 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_UNAVAILABLE;
+ goto error_out;
+ }
+
+ status = mech->gss_import_sec_context(mech->context, minor_status,
+ &token, &ctx->internal_ctx_id);
+
+ if (status == GSS_S_COMPLETE) {
+ *context_handle = (gss_ctx_id_t)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/usr/src/lib/libgss/g_init_sec_context.c b/usr/src/lib/libgss/g_init_sec_context.c
new file mode 100644
index 0000000000..c0743e41bf
--- /dev/null
+++ b/usr/src/lib/libgss/g_init_sec_context.c
@@ -0,0 +1,207 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine for gss_init_sec_context
+ */
+#include <mechglueP.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+OM_uint32
+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;
+const gss_cred_id_t claimant_cred_handle;
+gss_ctx_id_t *context_handle;
+const gss_name_t target_name;
+const gss_OID req_mech_type;
+OM_uint32 req_flags;
+OM_uint32 time_req;
+const gss_channel_bindings_t input_chan_bindings;
+const 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_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_C_NULL_OID;
+ gss_mechanism mech;
+ gss_cred_id_t input_cred_handle;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ /* clear output values */
+ if (actual_mech_type)
+ *actual_mech_type = NULL;
+
+ if (context_handle == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE | GSS_S_NO_CONTEXT);
+
+ if (target_name == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
+
+ if (output_token == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ output_token->value = NULL;
+ output_token->length = 0;
+
+
+ if (req_mech_type)
+ mech_type = (gss_OID)req_mech_type;
+
+ union_name = (gss_union_name_t)target_name;
+
+ /*
+ * 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->gss_init_sec_context == NULL)
+ return (GSS_S_UNAVAILABLE);
+
+ 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 &&
+ g_OID_equal(union_name->mech_type, mech_type)) {
+ internal_name = union_name->mech_name;
+ } else {
+ if ((status = __gss_import_internal_name(minor_status,
+ mech_type, union_name,
+ &internal_name)) != GSS_S_COMPLETE)
+ return (status);
+ }
+
+ /*
+ * 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) {
+ status = GSS_S_FAILURE;
+ union_ctx_id = (gss_union_ctx_id_t)
+ malloc(sizeof (gss_union_ctx_id_desc));
+ if (union_ctx_id == NULL)
+ goto end;
+
+ if (generic_gss_copy_oid(&temp_minor_status, mech_type,
+ &union_ctx_id->mech_type) != GSS_S_COMPLETE) {
+ free(union_ctx_id);
+ goto end;
+ }
+
+ /* copy the supplied context handle */
+ union_ctx_id->internal_ctx_id = *context_handle;
+ } else
+ union_ctx_id = (gss_union_ctx_id_t)*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
+ */
+
+ status = mech->gss_init_sec_context(
+ mech->context,
+ 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 (status != GSS_S_COMPLETE && status != GSS_S_CONTINUE_NEEDED) {
+ /*
+ * the spec says (the preferred) method is to delete all
+ * context info on the first call to init, and on all
+ * subsequent calls make the caller responsible for
+ * calling gss_delete_sec_context
+ */
+ if (*context_handle == GSS_C_NO_CONTEXT) {
+ free(union_ctx_id->mech_type->elements);
+ free(union_ctx_id->mech_type);
+ free(union_ctx_id);
+ }
+ } else if (*context_handle == GSS_C_NO_CONTEXT)
+ *context_handle = (gss_ctx_id_t)union_ctx_id;
+
+end:
+ if (union_name->mech_name == NULL ||
+ union_name->mech_name != internal_name) {
+ (void) __gss_release_internal_name(&temp_minor_status,
+ mech_type, &internal_name);
+ }
+
+ return (status);
+}
diff --git a/usr/src/lib/libgss/g_initialize.c b/usr/src/lib/libgss/g_initialize.c
new file mode 100644
index 0000000000..24d70252e5
--- /dev/null
+++ b/usr/src/lib/libgss/g_initialize.c
@@ -0,0 +1,938 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * This file contains functions to initialize the gssapi library and
+ * load mechanism libraries.
+ *
+ * It also contain functions requiring direct access to the mechanism's
+ * list (gss_inidicate_mechs and gss_release_oid) as well as support
+ * functions which translate the mechanism strings to oids and vise versa.
+ *
+ * The mechanism libraries are loaded on demand. This is triggered
+ * through the get_mechanism function call.
+ *
+ * Updates to the mechList are performed with the following restrictions:
+ * - once a library is loaded, none of the fields are updated
+ * - existing entiries for non-loaded mechs, will have the
+ * library and kernel module names updated only
+ * (i.e. the mech oid and mech name will not be updated)
+ */
+
+#include <mechglueP.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <errno.h>
+#include <synch.h>
+#include <dlfcn.h>
+#include <libintl.h>
+
+
+#ifndef TEXT_DOMAIN
+#error TEXT_DOMAIN not defined
+#endif
+
+#define MECH_CONF "/etc/gss/mech"
+
+#define MECH_LIB_PREFIX1 "/usr/lib/"
+
+/*
+ * This #ifdef mess figures out if we are to be compiled into
+ * a sparcv9/lp64 binary for the purposes of figuring the absolute location
+ * of gss-api mechanism modules.
+ */
+#ifdef _LP64
+
+#ifdef __sparc
+
+#define MECH_LIB_PREFIX2 "sparcv9/"
+
+#elif defined(__amd64)
+
+#define MECH_LIB_PREFIX2 "amd64/"
+
+#else /* __sparc */
+
+you need to define where under /usr the LP64 libraries live for this platform
+
+#endif /* __sparc */
+
+#else /* _LP64 */
+
+#define MECH_LIB_PREFIX2 ""
+
+#endif /* _LP64 */
+
+#define MECH_LIB_DIR "gss/"
+
+#define MECH_LIB_PREFIX MECH_LIB_PREFIX1 MECH_LIB_PREFIX2 MECH_LIB_DIR
+
+
+#ifndef MECH_SYM
+#define MECH_SYM "gss_mech_initialize"
+#endif
+
+#define M_DEFAULT "default"
+
+/* Local functions */
+static gss_mech_info searchMechList(const gss_OID);
+static void loadConfigFile(const char *);
+static void updateMechList(void);
+
+
+/*
+ * list of mechanism libraries and their entry points.
+ * the list also maintains state of the mech libraries (loaded or not).
+ */
+static gss_mech_info g_mechList = NULL;
+static gss_mech_info g_mechListTail = NULL;
+static mutex_t g_mechListLock;
+static time_t g_confFileModTime = (time_t)0;
+
+/*
+ * function used to reclaim the memory used by a gss_OID structure.
+ * This routine requires direct access to the mechList.
+ */
+OM_uint32
+gss_release_oid(minor_status, oid)
+OM_uint32 *minor_status;
+gss_OID *oid;
+{
+ OM_uint32 major;
+ gss_mech_info aMech = g_mechList;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *minor_status = 0;
+
+ while (aMech != NULL) {
+
+ /*
+ * look through the loaded mechanism libraries for
+ * gss_internal_release_oid 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.
+ */
+
+ /*
+ * we can walk the mechanism list without a mutex, because we
+ * are only looking at fields which once read will never change.
+ * Mechanism entries are always added to the end, and as
+ * complete entries.
+ */
+ if (aMech->mech && aMech->mech->gss_internal_release_oid) {
+ major = aMech->mech->gss_internal_release_oid(
+ aMech->mech->context,
+ minor_status, oid);
+ if (major == GSS_S_COMPLETE)
+ return (GSS_S_COMPLETE);
+ }
+ aMech = aMech->next;
+ } /* while */
+
+ return (generic_gss_release_oid(minor_status, oid));
+} /* gss_release_oid */
+
+
+/*
+ * this function will return an oid set indicating available mechanisms.
+ * The set returned is based on configuration file entries and
+ * NOT on the loaded mechanisms. This function does not check if any
+ * of these can actually be loaded.
+ * This routine needs direct access to the mechanism list.
+ * To avoid reading the configuration file each call, we will save a
+ * a mech oid set, and only update it once the file has changed.
+ */
+static time_t g_mechSetTime = (time_t)0;
+static gss_OID_set_desc g_mechSet = { 0, NULL };
+static mutex_t g_mechSetLock;
+
+
+OM_uint32
+gss_indicate_mechs(minorStatus, mechSet)
+OM_uint32 *minorStatus;
+gss_OID_set *mechSet;
+{
+ gss_mech_info mList;
+ char *fileName;
+ struct stat fileInfo;
+ int count, i, j;
+ gss_OID curItem;
+
+ if (!minorStatus)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *minorStatus = 0;
+
+
+ /* check output parameter */
+ if (mechSet == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ fileName = MECH_CONF;
+
+ /*
+ * If we have already computed the mechanisms supported and if it
+ * is still valid; make a copy and return to caller,
+ * otherwise build it first.
+ */
+ if ((stat(fileName, &fileInfo) == 0 &&
+ fileInfo.st_mtime > g_mechSetTime)) {
+ /*
+ * lock the mutex since we will be updating
+ * the mechList structure
+ * we need to keep the lock while we build the mechanism list
+ * since we are accessing parts of the mechList which could be
+ * modified.
+ */
+ (void) mutex_lock(&g_mechListLock);
+
+ /*
+ * this checks for the case when we need to re-construct the
+ * g_mechSet structure, but the mechanism list is upto date
+ * (because it has been read by someone calling
+ * __gss_get_mechanism)
+ */
+ if (fileInfo.st_mtime > g_confFileModTime)
+ {
+ g_confFileModTime = fileInfo.st_mtime;
+ loadConfigFile(fileName);
+ }
+
+ /*
+ * we need to lock the mech set so that no one else will
+ * try to read it as we are re-creating it
+ */
+ (void) mutex_lock(&g_mechSetLock);
+
+ /* if the oid list already exists we must free it first */
+ if (g_mechSet.count != 0) {
+ for (i = 0; i < g_mechSet.count; i++)
+ free(g_mechSet.elements[i].elements);
+ free(g_mechSet.elements);
+ g_mechSet.elements = NULL;
+ g_mechSet.count = 0;
+ }
+
+ /* determine how many elements to have in the list */
+ mList = g_mechList;
+ count = 0;
+ while (mList != NULL) {
+ count++;
+ mList = mList->next;
+ }
+
+ /* this should always be true, but.... */
+ if (count > 0) {
+ g_mechSet.elements =
+ (gss_OID) calloc(count, sizeof (gss_OID_desc));
+ if (g_mechSet.elements == NULL) {
+ (void) mutex_unlock(&g_mechSetLock);
+ (void) mutex_unlock(&g_mechListLock);
+ return (GSS_S_FAILURE);
+ }
+
+ (void) memset(g_mechSet.elements, 0,
+ count * sizeof (gss_OID_desc));
+
+ /* now copy each oid element */
+ g_mechSet.count = count;
+ count = 0;
+ mList = g_mechList;
+ while (mList != NULL) {
+ curItem = &(g_mechSet.elements[count]);
+ curItem->elements = (void*)
+ malloc(mList->mech_type->length);
+ if (curItem->elements == NULL) {
+ /*
+ * this is nasty - we must delete the
+ * part of the array already copied
+ */
+ for (i = 0; i < count; i++) {
+ free(g_mechSet.elements[i].
+ elements);
+ }
+ free(g_mechSet.elements);
+ g_mechSet.count = 0;
+ g_mechSet.elements = NULL;
+ (void) mutex_unlock(&g_mechSetLock);
+ (void) mutex_unlock(&g_mechListLock);
+ return (GSS_S_FAILURE);
+ }
+ g_OID_copy(curItem, mList->mech_type);
+ count++;
+ mList = mList->next;
+ }
+ }
+
+ g_mechSetTime = fileInfo.st_mtime;
+ (void) mutex_unlock(&g_mechSetLock);
+ (void) mutex_unlock(&g_mechListLock);
+ } /* if g_mechSet is out of date or not initialized */
+
+ /*
+ * the mech set is created and it is up to date
+ * so just copy it to caller
+ */
+ if ((*mechSet =
+ (gss_OID_set) malloc(sizeof (gss_OID_set_desc))) == NULL)
+ {
+ return (GSS_S_FAILURE);
+ }
+
+ /*
+ * need to lock the g_mechSet in case someone tries to update it while
+ * I'm copying it.
+ */
+ (void) mutex_lock(&g_mechSetLock);
+
+ /* allocate space for the oid structures */
+ if (((*mechSet)->elements =
+ (void*) calloc(g_mechSet.count, sizeof (gss_OID_desc)))
+ == NULL)
+ {
+ (void) mutex_unlock(&g_mechSetLock);
+ free(*mechSet);
+ *mechSet = NULL;
+ return (GSS_S_FAILURE);
+ }
+
+ /* now copy the oid structures */
+ (void) memcpy((*mechSet)->elements, g_mechSet.elements,
+ g_mechSet.count * sizeof (gss_OID_desc));
+
+ (*mechSet)->count = g_mechSet.count;
+
+ /* still need to copy each of the oid elements arrays */
+ for (i = 0; i < (*mechSet)->count; i++) {
+ curItem = &((*mechSet)->elements[i]);
+ curItem->elements =
+ (void *) malloc(g_mechSet.elements[i].length);
+ if (curItem->elements == NULL) {
+ (void) mutex_unlock(&g_mechSetLock);
+ /*
+ * must still free the allocated elements for
+ * each allocated gss_OID_desc
+ */
+ for (j = 0; j < i; j++) {
+ free((*mechSet)->elements[j].elements);
+ }
+ free((*mechSet)->elements);
+ free(mechSet);
+ *mechSet = NULL;
+ return (GSS_S_FAILURE);
+ }
+ g_OID_copy(curItem, &g_mechSet.elements[i]);
+ }
+ (void) mutex_unlock(&g_mechSetLock);
+ return (GSS_S_COMPLETE);
+} /* gss_indicate_mechs */
+
+/*
+ * this function has been added for use by modules that need to
+ * know what (if any) optional parameters are supplied in the
+ * config file (MECH_CONF).
+ * It will return the option string for a specified mechanism.
+ * caller is responsible for freeing the memory
+ */
+char *
+__gss_get_modOptions(oid)
+const gss_OID oid;
+{
+ gss_mech_info aMech;
+ char *modOptions = NULL;
+
+ /* make sure we have fresh data */
+ (void) mutex_lock(&g_mechListLock);
+ updateMechList();
+ (void) mutex_unlock(&g_mechListLock);
+
+ /* searching the list does not require a lock */
+ if ((aMech = searchMechList(oid)) == NULL ||
+ aMech->optionStr == NULL) {
+ return (NULL);
+ }
+
+ /*
+ * need to obtain a lock on this structure in case someone else
+ * will try to update it during the copy
+ */
+ (void) mutex_lock(&g_mechListLock);
+ if (aMech->optionStr)
+ modOptions = strdup(aMech->optionStr);
+ (void) mutex_unlock(&g_mechListLock);
+
+ return (modOptions);
+} /* __gss_get_modOptions */
+
+/*
+ * this function has been added for use by gssd.
+ * It will return the kernel module name for a specified mechanism.
+ * caller is responsible for freeing the memory
+ */
+char *
+__gss_get_kmodName(oid)
+const gss_OID oid;
+{
+ gss_mech_info aMech;
+ char *kmodName = NULL;
+
+ /* make sure we have fresh data */
+ (void) mutex_lock(&g_mechListLock);
+ updateMechList();
+ (void) mutex_unlock(&g_mechListLock);
+
+ /* searching the list does not require a lock */
+ if ((aMech = searchMechList(oid)) == NULL || aMech->kmodName == NULL) {
+ return (NULL);
+ }
+
+ /*
+ * need to obtain a lock on this structure in case someone else
+ * will try to update it during the copy
+ */
+ (void) mutex_lock(&g_mechListLock);
+ if (aMech->kmodName)
+ kmodName = strdup(aMech->kmodName);
+ (void) mutex_unlock(&g_mechListLock);
+
+ return (kmodName);
+} /* __gss_get_kmodName */
+
+
+/*
+ * given a mechanism string return the mechanism oid
+ */
+OM_uint32
+__gss_mech_to_oid(const char *mechStr, gss_OID* oid)
+{
+ gss_mech_info aMech;
+
+ if (oid == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *oid = GSS_C_NULL_OID;
+
+ if ((mechStr == NULL) || (strlen(mechStr) == 0) ||
+ (strcasecmp(mechStr, M_DEFAULT) == 0))
+ return (GSS_S_COMPLETE);
+
+ /* ensure we have fresh data */
+ (void) mutex_lock(&g_mechListLock);
+ updateMechList();
+ (void) mutex_unlock(&g_mechListLock);
+
+ aMech = g_mechList;
+
+ /* no lock required - only looking at fields that are not updated */
+ while (aMech != NULL) {
+ if ((aMech->mechNameStr) &&
+ strcmp(aMech->mechNameStr, mechStr) == 0) {
+ *oid = aMech->mech_type;
+ return (GSS_S_COMPLETE);
+ }
+ aMech = aMech->next;
+ }
+ return (GSS_S_FAILURE);
+} /* __gss_mech_to_oid */
+
+
+/*
+ * Given the mechanism oid, return the readable mechanism name
+ * associated with that oid from the mech config file
+ * (/etc/gss/mech).
+ */
+const char *
+__gss_oid_to_mech(const gss_OID oid)
+{
+ gss_mech_info aMech;
+
+ if (oid == GSS_C_NULL_OID)
+ return (M_DEFAULT);
+
+ /* ensure we have fresh data */
+ (void) mutex_lock(&g_mechListLock);
+ updateMechList();
+ (void) mutex_unlock(&g_mechListLock);
+
+ if ((aMech = searchMechList(oid)) == NULL)
+ return (NULL);
+
+ return (aMech->mechNameStr);
+} /* __gss_oid_to_mech */
+
+
+/*
+ * return a list of mechanism strings supported
+ * upon return the array is terminated with a NULL entry
+ */
+OM_uint32
+__gss_get_mechanisms(char *mechArray[], int arrayLen)
+{
+ gss_mech_info aMech;
+ int i;
+
+ if (mechArray == NULL || arrayLen < 1)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ /* ensure we have fresh data */
+ (void) mutex_lock(&g_mechListLock);
+ updateMechList();
+ (void) mutex_unlock(&g_mechListLock);
+
+ aMech = g_mechList;
+
+ /* no lock required - only looking at fields that are not updated */
+ for (i = 1; i < arrayLen; i++) {
+ if (aMech != NULL) {
+ *mechArray = aMech->mechNameStr;
+ mechArray++;
+ aMech = aMech->next;
+ } else
+ break;
+ }
+ *mechArray = NULL;
+ return (GSS_S_COMPLETE);
+} /* gss_get_mechanisms */
+
+
+/*
+ * determines if the mechList needs to be updated from file
+ * and performs the update.
+ * this functions must be called with a lock of g_mechListLock
+ */
+static void
+updateMechList(void)
+{
+ char *fileName;
+ struct stat fileInfo;
+
+ fileName = MECH_CONF;
+
+ /* check if mechList needs updating */
+ if (stat(fileName, &fileInfo) == 0 &&
+ (fileInfo.st_mtime > g_confFileModTime)) {
+ loadConfigFile(fileName);
+ g_confFileModTime = fileInfo.st_mtime;
+ }
+} /* updateMechList */
+
+
+/*
+ * given the mechanism type, return the mechanism structure
+ * containing the mechanism library entry points.
+ * will return NULL if mech type is not found
+ * This function will also trigger the loading of the mechanism
+ * module if it has not been already loaded.
+ */
+gss_mechanism
+__gss_get_mechanism(oid)
+const gss_OID oid;
+{
+ gss_mech_info aMech;
+ gss_mechanism (*sym)(const gss_OID);
+ void *dl;
+
+ /* check if the mechanism is already loaded */
+ if ((aMech = searchMechList(oid)) != NULL && aMech->mech) {
+ return (aMech->mech);
+ }
+
+ /*
+ * might need to re-read the configuration file before loading
+ * the mechanism to ensure we have the latest info.
+ */
+ (void) mutex_lock(&g_mechListLock);
+ updateMechList();
+
+ aMech = searchMechList(oid);
+
+ /* is the mechanism present in the list ? */
+ if (aMech == NULL) {
+ (void) mutex_unlock(&g_mechListLock);
+ return ((gss_mechanism)NULL);
+ }
+
+ /* has another thread loaded the mech */
+ if (aMech->mech) {
+ (void) mutex_unlock(&g_mechListLock);
+ return (aMech->mech);
+ }
+
+ /* we found the mechanism, but it is not loaded */
+ if ((dl = dlopen(aMech->uLibName, RTLD_NOW)) == NULL) {
+ (void) syslog(LOG_INFO, "libgss dlopen(%s): %s\n",
+ aMech->uLibName, dlerror());
+ (void) mutex_unlock(&g_mechListLock);
+ return ((gss_mechanism)NULL);
+ }
+
+ if ((sym = (gss_mechanism (*)(const gss_OID))dlsym(dl, MECH_SYM))
+ == NULL) {
+ (void) dlclose(dl);
+ (void) syslog(LOG_INFO, "unable to initialize mechanism"
+ " library [%s]\n", aMech->uLibName);
+ (void) mutex_unlock(&g_mechListLock);
+ return ((gss_mechanism)NULL);
+ }
+
+ /* Call the symbol to get the mechanism table */
+ aMech->mech = (*sym)(aMech->mech_type);
+
+ if (aMech->mech == NULL) {
+ (void) dlclose(dl);
+ (void) syslog(LOG_INFO, "unable to initialize mechanism"
+ " library [%s]\n", aMech->uLibName);
+ (void) mutex_unlock(&g_mechListLock);
+ return ((gss_mechanism)NULL);
+ }
+
+ aMech->dl_handle = dl;
+
+ (void) mutex_unlock(&g_mechListLock);
+ return (aMech->mech);
+} /* __gss_get_mechanism */
+
+gss_mechanism_ext
+__gss_get_mechanism_ext(oid)
+const gss_OID oid;
+{
+ gss_mech_info aMech;
+ gss_mechanism_ext mech_ext;
+
+ /* check if the mechanism is already loaded */
+ if ((aMech = searchMechList(oid)) != NULL && aMech->mech_ext != NULL)
+ return (aMech->mech_ext);
+
+ if (__gss_get_mechanism(oid) == NULL)
+ return (NULL);
+
+ if (aMech->dl_handle == NULL)
+ return (NULL);
+
+ /* Load the gss_config_ext struct for this mech */
+
+ mech_ext = (gss_mechanism_ext)malloc(sizeof (struct gss_config_ext));
+
+ if (mech_ext == NULL)
+ return (NULL);
+
+ /*
+ * dlsym() the mech's 'method' functions for the extended APIs
+ *
+ * NOTE: Until the void *context argument is removed from the
+ * SPI method functions' signatures it will be necessary to have
+ * different function pointer typedefs and function names for
+ * the SPI methods than for the API. When this argument is
+ * removed it will be possible to rename gss_*_sfct to gss_*_fct
+ * and and gssspi_* to gss_*.
+ */
+ mech_ext->gss_acquire_cred_with_password =
+ (gss_acquire_cred_with_password_sfct)dlsym(aMech->dl_handle,
+ "gssspi_acquire_cred_with_password");
+
+ /* Set aMech->mech_ext */
+ (void) mutex_lock(&g_mechListLock);
+
+ if (aMech->mech_ext == NULL)
+ aMech->mech_ext = mech_ext;
+ else
+ free(mech_ext); /* we raced and lost; don't leak */
+
+ (void) mutex_unlock(&g_mechListLock);
+
+ return (aMech->mech_ext);
+
+} /* __gss_get_mechanism_ext */
+
+
+/*
+ * this routine is used for searching the list of mechanism data.
+ * it needs not be mutex protected because we only add new structures
+ * from the end and they are fully initialized before being added.
+ */
+static gss_mech_info searchMechList(oid)
+const gss_OID oid;
+{
+ gss_mech_info aMech = g_mechList;
+
+ /* if oid is null -> then get default which is the first in the list */
+ if (oid == GSS_C_NULL_OID)
+ return (aMech);
+
+ while (aMech != NULL) {
+ if (g_OID_equal(aMech->mech_type, oid))
+ return (aMech);
+ aMech = aMech->next;
+ }
+
+ /* none found */
+ return ((gss_mech_info) NULL);
+} /* searchMechList */
+
+
+/*
+ * loads the configuration file
+ * this is called while having a mutex lock on the mechanism list
+ * entries for libraries that have been loaded can't be modified
+ * mechNameStr and mech_type fields are not updated during updates
+ */
+static void loadConfigFile(fileName)
+const char *fileName;
+{
+ char buffer[BUFSIZ], *oidStr, *oid, *sharedLib, *kernMod, *endp;
+ char *modOptions;
+ char sharedPath[sizeof (MECH_LIB_PREFIX) + BUFSIZ];
+ char *tmpStr;
+ FILE *confFile;
+ gss_OID mechOid;
+ gss_mech_info aMech, tmp;
+ OM_uint32 minor;
+ gss_buffer_desc oidBuf;
+
+ if ((confFile = fopen(fileName, "r")) == NULL) {
+ return;
+ }
+
+ (void) memset(buffer, 0, sizeof (buffer));
+ while (fgets(buffer, BUFSIZ, confFile) != NULL) {
+
+ /* ignore lines beginning with # */
+ if (*buffer == '#')
+ continue;
+
+ /*
+ * find the first white-space character after
+ * the mechanism name
+ */
+ oidStr = buffer;
+ for (oid = buffer; *oid && !isspace(*oid); oid++);
+
+ /* Now find the first non-white-space character */
+ if (*oid) {
+ *oid = '\0';
+ oid++;
+ while (*oid && isspace(*oid))
+ oid++;
+ }
+
+ /*
+ * If that's all, then this is a corrupt entry. Skip it.
+ */
+ if (! *oid)
+ continue;
+
+ /* Find the end of the oid and make sure it is NULL-ended */
+ for (endp = oid; *endp && !isspace(*endp); endp++)
+ ;
+
+ if (*endp) {
+ *endp = '\0';
+ }
+
+ /*
+ * check if an entry for this oid already exists
+ * if it does, and the library is already loaded then
+ * we can't modify it, so skip it
+ */
+ oidBuf.value = (void *)oid;
+ oidBuf.length = strlen(oid);
+ if (generic_gss_str_to_oid(&minor, &oidBuf, &mechOid)
+ != GSS_S_COMPLETE) {
+ (void) syslog(LOG_INFO, "invalid mechanism oid"
+ " [%s] in configuration file", oid);
+ continue;
+ }
+
+ aMech = searchMechList(mechOid);
+ if (aMech && aMech->mech) {
+ free(mechOid->elements);
+ free(mechOid);
+ continue;
+ }
+
+ /* Find the start of the shared lib name */
+ for (sharedLib = endp+1; *sharedLib && isspace(*sharedLib);
+ sharedLib++)
+ ;
+
+ /*
+ * If that's all, then this is a corrupt entry. Skip it.
+ */
+ if (! *sharedLib) {
+ free(mechOid->elements);
+ free(mechOid);
+ continue;
+ }
+
+ /*
+ * Find the end of the shared lib name and make sure it is
+ * NULL-terminated.
+ */
+ for (endp = sharedLib; *endp && !isspace(*endp); endp++)
+ ;
+
+ if (*endp) {
+ *endp = '\0';
+ }
+
+ /* Find the start of the optional kernel module lib name */
+ for (kernMod = endp+1; *kernMod && isspace(*kernMod);
+ kernMod++)
+ ;
+
+ /*
+ * If this item starts with a bracket "[", then
+ * it is not a kernel module, but is a list of
+ * options for the user module to parse later.
+ */
+ if (*kernMod && *kernMod != '[') {
+ /*
+ * Find the end of the shared lib name and make sure
+ * it is NULL-terminated.
+ */
+ for (endp = kernMod; *endp && !isspace(*endp); endp++)
+ ;
+
+ if (*endp) {
+ *endp = '\0';
+ }
+ } else
+ kernMod = NULL;
+
+ /* Find the start of the optional module options list */
+ for (modOptions = endp+1; *modOptions && isspace(*modOptions);
+ modOptions++);
+
+ if (*modOptions == '[') {
+ /* move past the opening bracket */
+ for (modOptions = modOptions+1;
+ *modOptions && isspace(*modOptions);
+ modOptions++);
+
+ /* Find the closing bracket */
+ for (endp = modOptions;
+ *endp && *endp != ']'; endp++);
+
+ if (endp)
+ *endp = '\0';
+
+ } else {
+ modOptions = NULL;
+ }
+
+ (void) strcpy(sharedPath, MECH_LIB_PREFIX);
+ (void) strcat(sharedPath, sharedLib);
+
+ /*
+ * are we creating a new mechanism entry or
+ * just modifying existing (non loaded) mechanism entry
+ */
+ if (aMech) {
+ /*
+ * delete any old values and set new
+ * mechNameStr and mech_type are not modified
+ */
+ if (aMech->kmodName) {
+ free(aMech->kmodName);
+ aMech->kmodName = NULL;
+ }
+
+ if (aMech->optionStr) {
+ free(aMech->optionStr);
+ aMech->optionStr = NULL;
+ }
+
+ if ((tmpStr = strdup(sharedPath)) != NULL) {
+ if (aMech->uLibName)
+ free(aMech->uLibName);
+ aMech->uLibName = tmpStr;
+ }
+
+ if (kernMod) /* this is an optional parameter */
+ aMech->kmodName = strdup(kernMod);
+
+ if (modOptions) /* optional module options */
+ aMech->optionStr = strdup(modOptions);
+
+ /* the oid is already set */
+ free(mechOid->elements);
+ free(mechOid);
+ continue;
+ }
+
+ /* adding a new entry */
+ aMech = malloc(sizeof (struct gss_mech_config));
+ if (aMech == NULL) {
+ free(mechOid->elements);
+ free(mechOid);
+ continue;
+ }
+ (void) memset(aMech, 0, sizeof (struct gss_mech_config));
+ aMech->mech_type = mechOid;
+ aMech->uLibName = strdup(sharedPath);
+ aMech->mechNameStr = strdup(oidStr);
+
+ /* check if any memory allocations failed - bad news */
+ if (aMech->uLibName == NULL || aMech->mechNameStr == NULL) {
+ if (aMech->uLibName)
+ free(aMech->uLibName);
+ if (aMech->mechNameStr)
+ free(aMech->mechNameStr);
+ free(mechOid->elements);
+ free(mechOid);
+ free(aMech);
+ continue;
+ }
+ if (kernMod) /* this is an optional parameter */
+ aMech->kmodName = strdup(kernMod);
+
+ if (modOptions)
+ aMech->optionStr = strdup(modOptions);
+ /*
+ * add the new entry to the end of the list - make sure
+ * that only complete entries are added because other
+ * threads might currently be searching the list.
+ */
+ tmp = g_mechListTail;
+ g_mechListTail = aMech;
+
+ if (tmp != NULL)
+ tmp->next = aMech;
+
+ if (g_mechList == NULL)
+ g_mechList = aMech;
+ } /* while */
+ (void) fclose(confFile);
+} /* loadConfigFile */
diff --git a/usr/src/lib/libgss/g_inquire_context.c b/usr/src/lib/libgss/g_inquire_context.c
new file mode 100644
index 0000000000..09ce566d3b
--- /dev/null
+++ b/usr/src/lib/libgss/g_inquire_context.c
@@ -0,0 +1,141 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine for gss_inquire_context
+ */
+
+#include <mechglueP.h>
+#include <stdlib.h>
+
+/* Last argument new for V2 */
+OM_uint32
+gss_inquire_context(
+ minor_status,
+ context_handle,
+ src_name,
+ targ_name,
+ lifetime_rec,
+ mech_type,
+ ctx_flags,
+ locally_initiated,
+ open)
+
+OM_uint32 *minor_status;
+const 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_name_t localTargName = NULL, localSourceName = NULL;
+
+ if (!minor_status)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *minor_status = 0;
+
+ /* if the context_handle is Null, return NO_CONTEXT error */
+ if (context_handle == GSS_C_NO_CONTEXT)
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+ /* set all output value to NULL */
+ if (src_name)
+ *src_name = NULL;
+
+ if (targ_name)
+ *targ_name = NULL;
+
+ if (mech_type)
+ *mech_type = NULL;
+
+ /*
+ * 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 ||
+ !mech->gss_release_name) {
+ return (GSS_S_UNAVAILABLE);
+ }
+
+ status = mech->gss_inquire_context(
+ mech->context,
+ minor_status,
+ ctx->internal_ctx_id,
+ (src_name ? &localSourceName : NULL),
+ (targ_name ? &localTargName : NULL),
+ lifetime_rec,
+ NULL,
+ 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,
+ localSourceName, src_name);
+ if (status != GSS_S_COMPLETE) {
+ if (localTargName)
+ mech->gss_release_name(mech->context,
+ &temp_minor, &localTargName);
+ return (status);
+ }
+ }
+
+ if (targ_name) {
+ status = __gss_convert_name_to_union_name(minor_status, mech,
+ localTargName, targ_name);
+
+ if (status != GSS_S_COMPLETE) {
+ if (src_name)
+ (void) gss_release_name(&temp_minor, src_name);
+
+ return (status);
+ }
+ }
+
+ /* spec says mech type must point to static storage */
+ if (mech_type)
+ *mech_type = &mech->mech_type;
+ return (GSS_S_COMPLETE);
+}
diff --git a/usr/src/lib/libgss/g_inquire_cred.c b/usr/src/lib/libgss/g_inquire_cred.c
new file mode 100644
index 0000000000..78fc641b74
--- /dev/null
+++ b/usr/src/lib/libgss/g_inquire_cred.c
@@ -0,0 +1,260 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine for gss_inquire_cred
+ */
+
+#include <mechglueP.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+OM_uint32
+gss_inquire_cred(minor_status,
+ cred_handle,
+ name,
+ lifetime,
+ cred_usage,
+ mechanisms)
+
+OM_uint32 *minor_status;
+const 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;
+
+ /* check parms and set to defaults */
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (name)
+ *name = NULL;
+
+ if (mechanisms)
+ *mechanisms = NULL;
+
+ 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_DEFECTIVE_CREDENTIAL);
+
+ if (!mech->gss_inquire_cred)
+ return (GSS_S_UNAVAILABLE);
+
+ status = mech->gss_inquire_cred(mech->context, minor_status,
+ 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) {
+ *minor_status = temp_minor_status;
+ if (mechanisms && *mechanisms) {
+ (void) gss_release_oid_set(
+ &temp_minor_status,
+ mechanisms);
+ }
+ 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() followed by gss_canonicalize_name()
+ * to get a mechanism specific name passed back to the caller.
+ * If this call fails, return failure to our caller.
+ * XXX The cred_handle may contain an array of mechanism OID's
+ * but we only return the MN for the first mechanism to the caller.
+ * In theory, we should modify this to provide an array of MN's
+ * one per mechanism back to the caller.
+ */
+
+ if (name != NULL) {
+ if ((gss_import_name(minor_status,
+ &union_cred->auxinfo.name,
+ union_cred->auxinfo.name_type,
+ name) != GSS_S_COMPLETE) ||
+ (gss_canonicalize_name(minor_status, *name,
+ &union_cred->mechs_array[0],
+ NULL) != GSS_S_COMPLETE)) {
+ status = GSS_S_DEFECTIVE_CREDENTIAL;
+ goto error;
+ }
+ }
+
+ /*
+ * copy the mechanism set in union_cred into an OID set and return in
+ * the mechanisms parameter.
+ */
+ if (mechanisms != NULL) {
+ status = GSS_S_FAILURE;
+ *mechanisms = (gss_OID_set) malloc(sizeof (gss_OID_set_desc));
+ if (*mechanisms == NULL)
+ goto error;
+
+ (*mechanisms)->count = 0;
+ (*mechanisms)->elements =
+ (gss_OID) malloc(sizeof (gss_OID_desc) *
+ union_cred->count);
+
+ if ((*mechanisms)->elements == NULL) {
+ free(*mechanisms);
+ *mechanisms = NULL;
+ goto error;
+ }
+
+ for (i = 0; i < union_cred->count; i++) {
+ (*mechanisms)->elements[i].elements = (void *)
+ malloc(union_cred->mechs_array[i].length);
+ if ((*mechanisms)->elements[i].elements == NULL)
+ goto error;
+ g_OID_copy(&(*mechanisms)->elements[i],
+ &union_cred->mechs_array[i]);
+ (*mechanisms)->count++;
+ }
+ }
+
+ return (GSS_S_COMPLETE);
+
+error:
+ /*
+ * cleanup any allocated memory - we can just call
+ * gss_release_oid_set, because the set is constructed so that
+ * count always references the currently copied number of
+ * elements.
+ */
+ if (mechanisms && *mechanisms != NULL)
+ (void) gss_release_oid_set(&temp_minor_status, mechanisms);
+
+ if (name && *name != NULL)
+ (void) gss_release_name(&temp_minor_status, name);
+
+ return (status);
+}
+
+OM_uint32
+gss_inquire_cred_by_mech(minor_status, cred_handle, mech_type, name,
+ initiator_lifetime, acceptor_lifetime, cred_usage)
+ OM_uint32 *minor_status;
+ const gss_cred_id_t cred_handle;
+ const 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;
+ OM_uint32 status, temp_minor_status;
+ gss_name_t internal_name;
+
+
+ mech = __gss_get_mechanism(mech_type);
+ if (!mech)
+ return (GSS_S_BAD_MECH);
+ if (!mech->gss_inquire_cred_by_mech)
+ return (GSS_S_UNAVAILABLE);
+
+ union_cred = (gss_union_cred_t)cred_handle;
+ mech_cred = __gss_get_mechanism_cred(union_cred, mech_type);
+ if (mech_cred == NULL)
+ return (GSS_S_DEFECTIVE_CREDENTIAL);
+
+ status = mech->gss_inquire_cred_by_mech(mech->context, minor_status,
+ mech_cred, mech_type,
+ name ? &internal_name : NULL,
+ initiator_lifetime,
+ acceptor_lifetime, cred_usage);
+
+ 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) {
+ *minor_status = temp_minor_status;
+ return (status);
+ }
+ }
+
+ return (GSS_S_COMPLETE);
+}
diff --git a/usr/src/lib/libgss/g_inquire_names.c b/usr/src/lib/libgss/g_inquire_names.c
new file mode 100644
index 0000000000..d24895bd90
--- /dev/null
+++ b/usr/src/lib/libgss/g_inquire_names.c
@@ -0,0 +1,162 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine for gss_inquire_context
+ */
+
+#include <mechglueP.h>
+
+#define MAX_MECH_OID_PAIRS 32
+
+/* Last argument new for V2 */
+OM_uint32
+gss_inquire_names_for_mech(minor_status, mechanism, name_types)
+
+OM_uint32 * minor_status;
+const gss_OID mechanism;
+gss_OID_set * name_types;
+
+{
+ OM_uint32 status;
+ gss_mechanism mech;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (name_types == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ /*
+ * 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(
+ mech->context,
+ minor_status,
+ mechanism,
+ name_types);
+ else
+ status = GSS_S_UNAVAILABLE;
+
+ return (status);
+ }
+
+ return (GSS_S_BAD_MECH);
+}
+
+OM_uint32
+gss_inquire_mechs_for_name(minor_status, input_name, mech_set)
+
+OM_uint32 * minor_status;
+const gss_name_t input_name;
+gss_OID_set * mech_set;
+
+{
+ OM_uint32 status;
+ static char *mech_list[MAX_MECH_OID_PAIRS+1];
+ gss_OID_set mech_name_types;
+ int present;
+ char *mechanism;
+ gss_OID mechOid;
+ gss_OID name_type;
+ gss_buffer_desc name_buffer;
+ int i;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (input_name == NULL)
+ return (GSS_S_BAD_NAME);
+
+ status = gss_create_empty_oid_set(minor_status, mech_set);
+ if (status != GSS_S_COMPLETE)
+ return (status);
+ *mech_list = NULL;
+ status = __gss_get_mechanisms(mech_list, MAX_MECH_OID_PAIRS+1);
+ if (status != GSS_S_COMPLETE)
+ return (status);
+ for (i = 0; i < MAX_MECH_OID_PAIRS && mech_list[i] != NULL; i++) {
+ mechanism = mech_list[i];
+ if (__gss_mech_to_oid(mechanism, &mechOid) == GSS_S_COMPLETE) {
+ status = gss_inquire_names_for_mech(
+ minor_status,
+ mechOid,
+ &mech_name_types);
+ if (status == GSS_S_COMPLETE) {
+ status = gss_display_name(minor_status,
+ input_name,
+ &name_buffer,
+ &name_type);
+
+ (void) gss_release_buffer(NULL, &name_buffer);
+
+ if (status == GSS_S_COMPLETE && name_type) {
+ status = gss_test_oid_set_member(
+ minor_status,
+ name_type,
+ mech_name_types,
+ &present);
+ if (status == GSS_S_COMPLETE &&
+ present) {
+ status = gss_add_oid_set_member(
+ minor_status,
+ mechOid,
+ mech_set);
+ if (status != GSS_S_COMPLETE) {
+ (void) gss_release_oid_set(
+ minor_status,
+ &mech_name_types);
+ (void) gss_release_oid_set(
+ minor_status,
+ mech_set);
+ return (status);
+ }
+ }
+ }
+ (void) gss_release_oid_set(
+ minor_status,
+ &mech_name_types);
+ }
+ } else {
+ (void) gss_release_oid_set(
+ minor_status,
+ mech_set);
+ return (GSS_S_FAILURE);
+ }
+ }
+ return (GSS_S_COMPLETE);
+}
diff --git a/usr/src/lib/libgss/g_oid_ops.c b/usr/src/lib/libgss/g_oid_ops.c
new file mode 100644
index 0000000000..7694b7e445
--- /dev/null
+++ b/usr/src/lib/libgss/g_oid_ops.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1996,1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+#pragma ident "%Z%%M% %I% %E% SMI"
+/*
+ * 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. 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 <mechglueP.h>
+
+/*
+ * gss_release_oid has been moved to g_initialize, becasue it requires access
+ * to the mechanism list. All functions requiring direct access to the
+ * mechanism list are now in g_initialize.c
+ */
+
+OM_uint32
+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
+gss_add_oid_set_member(minor_status, member_oid, oid_set)
+ OM_uint32 *minor_status;
+ const gss_OID member_oid;
+ gss_OID_set *oid_set;
+{
+ return (generic_gss_add_oid_set_member(minor_status, member_oid,
+ oid_set));
+}
+
+OM_uint32
+gss_test_oid_set_member(minor_status, member, set, present)
+ OM_uint32 *minor_status;
+ const gss_OID member;
+ const gss_OID_set set;
+ int *present;
+{
+ return (generic_gss_test_oid_set_member(minor_status, member, set,
+ present));
+}
+
+OM_uint32
+gss_oid_to_str(minor_status, oid, oid_str)
+ OM_uint32 *minor_status;
+ const gss_OID oid;
+ gss_buffer_t oid_str;
+{
+ return (generic_gss_oid_to_str(minor_status, oid, oid_str));
+}
+
+OM_uint32
+gss_str_to_oid(minor_status, oid_str, oid)
+ OM_uint32 *minor_status;
+ const gss_buffer_t oid_str;
+ gss_OID *oid;
+{
+ return (generic_gss_str_to_oid(minor_status, oid_str, oid));
+}
diff --git a/usr/src/lib/libgss/g_process_context.c b/usr/src/lib/libgss/g_process_context.c
new file mode 100644
index 0000000000..b1f3b18c94
--- /dev/null
+++ b/usr/src/lib/libgss/g_process_context.c
@@ -0,0 +1,82 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996,1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine gss_process_context
+ */
+
+#include <mechglueP.h>
+
+OM_uint32
+gss_process_context_token(minor_status,
+ context_handle,
+ token_buffer)
+
+OM_uint32 * minor_status;
+const gss_ctx_id_t context_handle;
+gss_buffer_t token_buffer;
+
+{
+ OM_uint32 status;
+ gss_union_ctx_id_t ctx;
+ gss_mechanism mech;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (context_handle == GSS_C_NO_CONTEXT)
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+ if (GSS_EMPTY_BUFFER(token_buffer))
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ /*
+ * 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(
+ mech->context,
+ minor_status,
+ ctx->internal_ctx_id,
+ token_buffer);
+ else
+ status = GSS_S_UNAVAILABLE;
+
+ return (status);
+ }
+
+ return (GSS_S_BAD_MECH);
+}
diff --git a/usr/src/lib/libgss/g_rel_buffer.c b/usr/src/lib/libgss/g_rel_buffer.c
new file mode 100644
index 0000000000..ec8ac8845d
--- /dev/null
+++ b/usr/src/lib/libgss/g_rel_buffer.c
@@ -0,0 +1,60 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996,1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine for gss_release_buffer
+ */
+
+#include <mechglueP.h>
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+OM_uint32
+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/usr/src/lib/libgss/g_rel_cred.c b/usr/src/lib/libgss/g_rel_cred.c
new file mode 100644
index 0000000000..b694bceaaa
--- /dev/null
+++ b/usr/src/lib/libgss/g_rel_cred.c
@@ -0,0 +1,100 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine for gss_release_cred
+ */
+
+#include <mechglueP.h>
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+OM_uint32
+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;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *minor_status = 0;
+
+ if (cred_handle == NULL)
+ return (GSS_S_NO_CRED | GSS_S_CALL_INACCESSIBLE_READ);
+
+ /*
+ * 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 == (gss_union_cred_t)GSS_C_NO_CREDENTIAL)
+ return (GSS_S_COMPLETE);
+
+ 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
+ (mech->context, minor_status,
+ &union_cred->cred_array[j]);
+
+ if (temp_status != GSS_S_COMPLETE)
+ status = GSS_S_NO_CRED;
+ } else
+ status = GSS_S_UNAVAILABLE;
+ } else
+ status = GSS_S_DEFECTIVE_CREDENTIAL;
+ }
+
+ (void) 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/usr/src/lib/libgss/g_rel_name.c b/usr/src/lib/libgss/g_rel_name.c
new file mode 100644
index 0000000000..e4df5438f2
--- /dev/null
+++ b/usr/src/lib/libgss/g_rel_name.c
@@ -0,0 +1,83 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine for gss_release_name
+ */
+
+#include <mechglueP.h>
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+OM_uint32
+gss_release_name(minor_status,
+ input_name)
+
+OM_uint32 *minor_status;
+gss_name_t *input_name;
+
+{
+ gss_union_name_t union_name;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ /* if input_name is NULL, return error */
+ if (input_name == 0)
+ return (GSS_S_CALL_INACCESSIBLE_READ | 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->name_type)
+ (void) gss_release_oid(minor_status, &union_name->name_type);
+
+ free(union_name->external_name->value);
+ free(union_name->external_name);
+
+ if (union_name->mech_type) {
+ (void) __gss_release_internal_name(minor_status,
+ union_name->mech_type,
+ &union_name->mech_name);
+ (void) gss_release_oid(minor_status, &union_name->mech_type);
+ }
+
+ free(union_name);
+
+ return (GSS_S_COMPLETE);
+}
diff --git a/usr/src/lib/libgss/g_rel_oid_set.c b/usr/src/lib/libgss/g_rel_oid_set.c
new file mode 100644
index 0000000000..bddc1bc43b
--- /dev/null
+++ b/usr/src/lib/libgss/g_rel_oid_set.c
@@ -0,0 +1,66 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996,1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine for gss_release_oid_set
+ */
+
+#include <mechglueP.h>
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+OM_uint32
+gss_release_oid_set(minor_status, set)
+
+OM_uint32 * minor_status;
+gss_OID_set * set;
+{
+ OM_uint32 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/usr/src/lib/libgss/g_seal.c b/usr/src/lib/libgss/g_seal.c
new file mode 100644
index 0000000000..db1fac77da
--- /dev/null
+++ b/usr/src/lib/libgss/g_seal.c
@@ -0,0 +1,169 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996,1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine for gss_seal
+ */
+
+#include <mechglueP.h>
+
+/*ARGSUSED*/
+OM_uint32
+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;
+{
+/* EXPORT DELETE START */
+
+ OM_uint32 status;
+ gss_union_ctx_id_t ctx;
+ gss_mechanism mech;
+
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (context_handle == GSS_C_NO_CONTEXT)
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+ if (input_message_buffer == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if (output_message_buffer == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ /*
+ * 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(
+ mech->context,
+ minor_status,
+ ctx->internal_ctx_id,
+ conf_req_flag,
+ qop_req,
+ input_message_buffer,
+ conf_state,
+ output_message_buffer);
+ else
+ status = GSS_S_UNAVAILABLE;
+
+ return (status);
+ }
+/* EXPORT DELETE END */
+
+ return (GSS_S_BAD_MECH);
+}
+
+OM_uint32
+gss_wrap(minor_status,
+ context_handle,
+ conf_req_flag,
+ qop_req,
+ input_message_buffer,
+ conf_state,
+ output_message_buffer)
+
+OM_uint32 * minor_status;
+const gss_ctx_id_t context_handle;
+int conf_req_flag;
+gss_qop_t qop_req;
+const gss_buffer_t input_message_buffer;
+int * conf_state;
+gss_buffer_t output_message_buffer;
+
+{
+ return gss_seal(minor_status, (gss_ctx_id_t)context_handle,
+ conf_req_flag, (int) qop_req,
+ (gss_buffer_t)input_message_buffer, conf_state,
+ output_message_buffer);
+}
+
+/*
+ * New for V2
+ */
+OM_uint32
+gss_wrap_size_limit(minor_status, context_handle, conf_req_flag,
+ qop_req, req_output_size, max_input_size)
+ OM_uint32 *minor_status;
+ const 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;
+{
+ gss_union_ctx_id_t ctx;
+ gss_mechanism mech;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (context_handle == GSS_C_NO_CONTEXT)
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+ if (max_input_size == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ /*
+ * 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_wrap_size_limit)
+ return (GSS_S_UNAVAILABLE);
+
+ return (mech->gss_wrap_size_limit(mech->context, minor_status,
+ ctx->internal_ctx_id, conf_req_flag, qop_req,
+ req_output_size, max_input_size));
+}
diff --git a/usr/src/lib/libgss/g_sign.c b/usr/src/lib/libgss/g_sign.c
new file mode 100644
index 0000000000..fa5edbd54d
--- /dev/null
+++ b/usr/src/lib/libgss/g_sign.c
@@ -0,0 +1,110 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996,1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine gss_sign
+ */
+
+#include <mechglueP.h>
+
+OM_uint32
+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;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (context_handle == GSS_C_NO_CONTEXT)
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+ if (message_buffer == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if (msg_token == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ msg_token->value = NULL;
+ msg_token->length = 0;
+ /*
+ * 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(
+ mech->context,
+ minor_status,
+ ctx->internal_ctx_id,
+ qop_req,
+ message_buffer,
+ msg_token);
+ else
+ status = GSS_S_UNAVAILABLE;
+
+ return (status);
+ }
+
+ return (GSS_S_BAD_MECH);
+}
+
+OM_uint32
+gss_get_mic(minor_status,
+ context_handle,
+ qop_req,
+ message_buffer,
+ msg_token)
+
+OM_uint32 * minor_status;
+const gss_ctx_id_t context_handle;
+gss_qop_t qop_req;
+const gss_buffer_t message_buffer;
+gss_buffer_t msg_token;
+
+{
+ return (gss_sign(minor_status, (gss_ctx_id_t)context_handle,
+ (int) qop_req, (gss_buffer_t)message_buffer, msg_token));
+}
diff --git a/usr/src/lib/libgss/g_store_cred.c b/usr/src/lib/libgss/g_store_cred.c
new file mode 100644
index 0000000000..5191640c28
--- /dev/null
+++ b/usr/src/lib/libgss/g_store_cred.c
@@ -0,0 +1,157 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine for gss_store_cred
+ */
+
+#include <mechglueP.h>
+
+OM_uint32 gss_store_cred(minor_status,
+ input_cred_handle,
+ cred_usage,
+ desired_mech,
+ overwrite_cred,
+ default_cred,
+ elements_stored,
+ cred_usage_stored)
+
+OM_uint32 *minor_status;
+const gss_cred_id_t input_cred_handle;
+gss_cred_usage_t cred_usage;
+const gss_OID desired_mech;
+OM_uint32 overwrite_cred;
+OM_uint32 default_cred;
+gss_OID_set *elements_stored;
+gss_cred_usage_t *cred_usage_stored;
+
+{
+ OM_uint32 major_status = GSS_S_FAILURE;
+ gss_union_cred_t union_cred;
+ gss_cred_id_t mech_cred;
+ gss_mechanism mech;
+ gss_OID dmech;
+ int i;
+
+ /* Start by checking parameters */
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE|GSS_S_NO_CRED);
+ *minor_status = 0;
+
+ if (input_cred_handle == GSS_C_NO_CREDENTIAL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if (elements_stored != NULL)
+ *elements_stored = GSS_C_NULL_OID_SET;
+
+ if (cred_usage_stored != NULL)
+ *cred_usage_stored = GSS_C_BOTH; /* there's no GSS_C_NEITHER */
+
+ union_cred = (gss_union_cred_t)input_cred_handle;
+
+ /* desired_mech != GSS_C_NULL_OID -> store one element */
+ if (desired_mech != GSS_C_NULL_OID) {
+ mech = __gss_get_mechanism(desired_mech);
+ if (mech == NULL)
+ return (GSS_S_BAD_MECH);
+
+ if (mech->gss_store_cred == NULL)
+ return (major_status);
+
+ mech_cred = __gss_get_mechanism_cred(union_cred, desired_mech);
+ if (mech_cred == GSS_C_NO_CREDENTIAL)
+ return (GSS_S_NO_CRED);
+
+ return (mech->gss_store_cred(mech->context,
+ minor_status,
+ (gss_cred_id_t)mech_cred,
+ cred_usage,
+ desired_mech,
+ overwrite_cred,
+ default_cred,
+ elements_stored,
+ cred_usage_stored));
+ }
+
+ /* desired_mech == GSS_C_NULL_OID -> store all elements */
+
+ *minor_status = 0;
+
+ for (i = 0; i < union_cred->count; i++) {
+ /* Get mech and cred element */
+ dmech = &union_cred->mechs_array[i];
+ mech = __gss_get_mechanism(dmech);
+ if (mech == NULL)
+ continue;
+
+ if (mech->gss_store_cred == NULL)
+ continue;
+
+ mech_cred = __gss_get_mechanism_cred(union_cred, dmech);
+ if (mech_cred == GSS_C_NO_CREDENTIAL)
+ continue; /* can't happen, but safe to ignore */
+
+ major_status = mech->gss_store_cred(mech->context,
+ minor_status,
+ (gss_cred_id_t)mech_cred,
+ cred_usage,
+ dmech,
+ overwrite_cred,
+ default_cred,
+ NULL,
+ cred_usage_stored);
+ if (major_status != GSS_S_COMPLETE)
+ continue;
+
+ /* Succeeded for at least one mech */
+
+ if (elements_stored == NULL)
+ continue;
+
+ if (*elements_stored == GSS_C_NULL_OID_SET) {
+ major_status = gss_create_empty_oid_set(minor_status,
+ elements_stored);
+
+ if (GSS_ERROR(major_status))
+ return (major_status);
+ }
+
+ major_status = gss_add_oid_set_member(minor_status, dmech,
+ elements_stored);
+
+ /* The caller should clean up elements_stored */
+ if (GSS_ERROR(major_status))
+ return (major_status);
+ }
+
+ /*
+ * Success with some mechs may mask failure with others, but
+ * that's what elements_stored is for.
+ */
+ return (major_status);
+}
diff --git a/usr/src/lib/libgss/g_unseal.c b/usr/src/lib/libgss/g_unseal.c
new file mode 100644
index 0000000000..05c8e21eff
--- /dev/null
+++ b/usr/src/lib/libgss/g_unseal.c
@@ -0,0 +1,120 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996,1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine gss_unseal
+ */
+
+#include <mechglueP.h>
+
+OM_uint32
+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;
+
+{
+/* EXPORT DELETE START */
+ OM_uint32 status;
+ gss_union_ctx_id_t ctx;
+ gss_mechanism mech;
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (context_handle == GSS_C_NO_CONTEXT)
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+ if (GSS_EMPTY_BUFFER(input_message_buffer))
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if (output_message_buffer == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ output_message_buffer->length = 0;
+ output_message_buffer->value = NULL;
+
+ /*
+ * 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(
+ mech->context,
+ minor_status,
+ ctx->internal_ctx_id,
+ input_message_buffer,
+ output_message_buffer,
+ conf_state,
+ qop_state);
+ else
+ status = GSS_S_UNAVAILABLE;
+
+ return (status);
+ }
+
+/* EXPORT DELETE END */
+
+ return (GSS_S_BAD_MECH);
+}
+
+OM_uint32
+gss_unwrap(minor_status,
+ context_handle,
+ input_message_buffer,
+ output_message_buffer,
+ conf_state,
+ qop_state)
+
+OM_uint32 * minor_status;
+const gss_ctx_id_t context_handle;
+const 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, (gss_ctx_id_t)context_handle,
+ (gss_buffer_t)input_message_buffer,
+ output_message_buffer, conf_state, (int *) qop_state));
+}
diff --git a/usr/src/lib/libgss/g_userok.c b/usr/src/lib/libgss/g_userok.c
new file mode 100644
index 0000000000..6b6f6c2215
--- /dev/null
+++ b/usr/src/lib/libgss/g_userok.c
@@ -0,0 +1,133 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <deflt.h>
+#include <mechglueP.h>
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_ext.h>
+
+
+static OM_uint32
+compare_names(OM_uint32 *minor,
+ const gss_OID mech_type,
+ const gss_name_t name,
+ const char *user,
+ int *user_ok)
+{
+
+ OM_uint32 status, tmpMinor;
+ gss_name_t imported_name;
+ gss_name_t canon_name;
+ gss_buffer_desc gss_user;
+ int match = 0;
+
+ *user_ok = 0;
+
+ gss_user.value = (void *)user;
+ if (!gss_user.value || !name || !mech_type)
+ return (GSS_S_BAD_NAME);
+ gss_user.length = strlen(gss_user.value);
+
+ status = gss_import_name(minor,
+ &gss_user,
+ GSS_C_NT_USER_NAME,
+ &imported_name);
+ if (status != GSS_S_COMPLETE) {
+ goto out;
+ }
+
+ status = gss_canonicalize_name(minor,
+ imported_name,
+ mech_type,
+ &canon_name);
+ if (status != GSS_S_COMPLETE) {
+ (void) gss_release_name(&tmpMinor, &imported_name);
+ goto out;
+ }
+
+ status = gss_compare_name(minor,
+ canon_name,
+ name,
+ &match);
+ (void) gss_release_name(&tmpMinor, &canon_name);
+ (void) gss_release_name(&tmpMinor, &imported_name);
+ if (status == GSS_S_COMPLETE) {
+ if (match)
+ *user_ok = 1; /* remote user is a-ok */
+ }
+
+out:
+ return (status);
+}
+
+
+OM_uint32
+__gss_userok(OM_uint32 *minor,
+ const gss_name_t name,
+ const char *user,
+ int *user_ok)
+
+{
+ gss_mechanism mech;
+ gss_union_name_t intName;
+ gss_name_t mechName = NULL;
+ OM_uint32 major;
+
+ if (minor == NULL || user_ok == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ if (name == NULL || user == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ *user_ok = 0;
+ *minor = GSS_S_COMPLETE;
+
+ intName = (gss_union_name_t)name;
+
+ mech = __gss_get_mechanism(intName->mech_type);
+ if (mech == NULL)
+ return (GSS_S_UNAVAILABLE);
+
+ /* may need to import the name if this is not MN */
+ if (intName->mech_type == NULL) {
+ return (GSS_S_FAILURE);
+ } else
+ mechName = intName->mech_name;
+
+ if (mech->__gss_userok)
+ major = mech->__gss_userok(mech->context, minor, mechName,
+ user, user_ok);
+ else
+ major = compare_names(minor, intName->mech_type,
+ name, user, user_ok);
+
+ return (major);
+} /* gss_userok */
diff --git a/usr/src/lib/libgss/g_utils.c b/usr/src/lib/libgss/g_utils.c
new file mode 100644
index 0000000000..7e7183f912
--- /dev/null
+++ b/usr/src/lib/libgss/g_utils.c
@@ -0,0 +1,302 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <ctype.h>
+#include <errno.h>
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_ext.h>
+#include <synch.h>
+
+#define Q_DEFAULT "default"
+#define BUFLEN 256
+
+static int qop_num_pair_cnt;
+static const char QOP_NUM_FILE[] = "/etc/gss/qop";
+static qop_num qop_num_pairs[MAX_QOP_NUM_PAIRS+1];
+static mutex_t qopfile_lock = DEFAULTMUTEX;
+
+static OM_uint32 __gss_read_qop_file(void);
+
+/*
+ * This routine fetches qop and num from "/etc/gss/qop".
+ * There is a memory leak associated with rereading this file,
+ * because we can't free the qop_num_pairs array when we reread
+ * the file (some callers may have been given these pointers).
+ * In general, this memory leak should be a small one, because
+ * we don't expect the qop file to be changed and reread often.
+ */
+static OM_uint32
+__gss_read_qop_file(void)
+{
+ char buf[BUFLEN]; /* one line from the file */
+ char *name, *next;
+ char *qopname, *num_str;
+ char *line;
+ FILE *fp;
+ static int last = 0;
+ struct stat stbuf;
+ OM_uint32 major = GSS_S_COMPLETE;
+
+ (void) mutex_lock(&qopfile_lock);
+ if (stat(QOP_NUM_FILE, &stbuf) != 0 || stbuf.st_mtime < last) {
+ if (!qop_num_pairs[0].qop) {
+ major = GSS_S_FAILURE;
+ }
+ goto done;
+ }
+ last = stbuf.st_mtime;
+
+ fp = fopen(QOP_NUM_FILE, "r");
+ if (fp == (FILE *)0) {
+ major = GSS_S_FAILURE;
+ goto done;
+ }
+
+ /*
+ * For each line in the file parse it appropriately.
+ * File format : qopname num(int)
+ * Note that we silently ignore corrupt entries.
+ */
+ qop_num_pair_cnt = 0;
+ while (!feof(fp)) {
+ line = fgets(buf, BUFLEN, fp);
+ if (line == NULL)
+ break;
+
+ /* Skip comments and blank lines */
+ if ((*line == '#') || (*line == '\n'))
+ continue;
+
+ /* Skip trailing comments */
+ next = strchr(line, '#');
+ if (next)
+ *next = '\0';
+
+ name = &(buf[0]);
+ while (isspace(*name))
+ name++;
+ if (*name == '\0') /* blank line */
+ continue;
+
+ qopname = name; /* will contain qop name */
+ while (!isspace(*qopname))
+ qopname++;
+ if (*qopname == '\0') {
+ continue;
+ }
+ next = qopname+1;
+ *qopname = '\0'; /* null terminate qopname */
+ qop_num_pairs[qop_num_pair_cnt].qop = strdup(name);
+ if (qop_num_pairs[qop_num_pair_cnt].qop == NULL)
+ continue;
+
+ name = next;
+ while (isspace(*name))
+ name++;
+ if (*name == '\0') { /* end of line, no num */
+ free(qop_num_pairs[qop_num_pair_cnt].qop);
+ continue;
+ }
+ num_str = name; /* will contain num (n) */
+ while (!isspace(*num_str))
+ num_str++;
+ next = num_str+1;
+ *num_str++ = '\0'; /* null terminate num_str */
+
+ qop_num_pairs[qop_num_pair_cnt].num = (OM_uint32)atoi(name);
+ name = next;
+ while (isspace(*name))
+ name++;
+ if (*name == '\0') { /* end of line, no mechanism */
+ free(qop_num_pairs[qop_num_pair_cnt].qop);
+ continue;
+ }
+ num_str = name; /* will contain mech */
+ while (!isspace(*num_str))
+ num_str++;
+ *num_str = '\0';
+
+ qop_num_pairs[qop_num_pair_cnt].mech = strdup(name);
+ if (qop_num_pairs[qop_num_pair_cnt].mech == NULL) {
+ free(qop_num_pairs[qop_num_pair_cnt].qop);
+ continue;
+ }
+
+ if (qop_num_pair_cnt++ >= MAX_QOP_NUM_PAIRS)
+ break;
+ }
+ (void) fclose(fp);
+done:
+ (void) mutex_unlock(&qopfile_lock);
+ return (major);
+}
+
+OM_uint32
+__gss_qop_to_num(
+ char *qop,
+ char *mech,
+ OM_uint32 *num
+)
+{
+ int i;
+ OM_uint32 major = GSS_S_FAILURE;
+
+ if (!num)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ if (qop == NULL || strlen(qop) == 0 ||
+ strcasecmp(qop, Q_DEFAULT) == 0) {
+ *num = GSS_C_QOP_DEFAULT;
+ return (GSS_S_COMPLETE);
+ }
+
+ if ((major = __gss_read_qop_file()) != GSS_S_COMPLETE)
+ return (major);
+
+ for (i = 0; i < qop_num_pair_cnt; i++) {
+ if ((strcasecmp(mech, qop_num_pairs[i].mech) == 0) &&
+ (strcasecmp(qop, qop_num_pairs[i].qop) == 0)) {
+ *num = qop_num_pairs[i].num;
+ return (GSS_S_COMPLETE);
+ }
+ }
+
+ return (GSS_S_FAILURE);
+}
+
+OM_uint32
+__gss_num_to_qop(
+ char *mech,
+ OM_uint32 num,
+ char **qop
+)
+{
+ int i;
+ OM_uint32 major;
+
+ if (!qop)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *qop = NULL;
+
+ if (num == GSS_C_QOP_DEFAULT) {
+ *qop = Q_DEFAULT;
+ return (GSS_S_COMPLETE);
+ }
+
+ if (mech == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if ((major = __gss_read_qop_file()) != GSS_S_COMPLETE)
+ return (major);
+
+ for (i = 0; i < qop_num_pair_cnt; i++) {
+ if ((strcasecmp(mech, qop_num_pairs[i].mech) == 0) &&
+ (num == qop_num_pairs[i].num)) {
+ *qop = qop_num_pairs[i].qop;
+ return (GSS_S_COMPLETE);
+ }
+ }
+ return (GSS_S_FAILURE);
+}
+
+/*
+ * For a given mechanism pass back qop information about it in a buffer
+ * of size MAX_QOPS_PER_MECH+1.
+ */
+OM_uint32
+__gss_get_mech_info(
+ char *mech,
+ char **qops
+)
+{
+ int i, cnt = 0;
+ OM_uint32 major = GSS_S_COMPLETE;
+
+ if (!qops)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *qops = NULL;
+
+ if (!mech)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if ((major = __gss_read_qop_file()) != GSS_S_COMPLETE)
+ return (major);
+
+ for (i = 0; i < qop_num_pair_cnt; i++) {
+ if (strcmp(mech, qop_num_pairs[i].mech) == 0) {
+ if (cnt >= MAX_QOPS_PER_MECH) {
+ return (GSS_S_FAILURE);
+ }
+ qops[cnt++] = qop_num_pairs[i].qop;
+ }
+ }
+ qops[cnt] = NULL;
+ return (GSS_S_COMPLETE);
+}
+
+/*
+ * Copy the qop values and names for the mechanism back in a qop_num
+ * buffer of size MAX_QOPS_PER_MECH provided by the caller.
+ */
+OM_uint32
+__gss_mech_qops(
+ char *mech,
+ qop_num *mechqops,
+ int *numqop
+)
+{
+ int i;
+ OM_uint32 major;
+ int cnt = 0;
+
+ if (!mechqops || !numqop)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *numqop = 0;
+
+ if (!mech)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if ((major = __gss_read_qop_file()) != GSS_S_COMPLETE)
+ return (major);
+
+ for (i = 0; i < qop_num_pair_cnt; i++) {
+ if (strcasecmp(mech, qop_num_pairs[i].mech) == 0) {
+ if (cnt >= MAX_QOPS_PER_MECH) {
+ return (GSS_S_FAILURE);
+ }
+ mechqops[cnt++] = qop_num_pairs[i];
+ }
+ }
+ *numqop = cnt;
+ return (GSS_S_COMPLETE);
+}
diff --git a/usr/src/lib/libgss/g_verify.c b/usr/src/lib/libgss/g_verify.c
new file mode 100644
index 0000000000..2d4ec3de53
--- /dev/null
+++ b/usr/src/lib/libgss/g_verify.c
@@ -0,0 +1,106 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1996,1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * glue routine for gss_verify
+ */
+
+#include <mechglueP.h>
+
+OM_uint32
+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;
+
+
+ if (minor_status == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+ *minor_status = 0;
+
+ if (context_handle == GSS_C_NO_CONTEXT)
+ return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT);
+
+ if ((message_buffer == NULL) || GSS_EMPTY_BUFFER(token_buffer))
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ /*
+ * 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(
+ mech->context,
+ minor_status,
+ ctx->internal_ctx_id,
+ message_buffer,
+ token_buffer,
+ qop_state);
+ else
+ status = GSS_S_UNAVAILABLE;
+
+ return (status);
+ }
+
+ return (GSS_S_BAD_MECH);
+}
+
+OM_uint32
+gss_verify_mic(minor_status,
+ context_handle,
+ message_buffer,
+ token_buffer,
+ qop_state)
+
+OM_uint32 * minor_status;
+const gss_ctx_id_t context_handle;
+const gss_buffer_t message_buffer;
+const gss_buffer_t token_buffer;
+gss_qop_t * qop_state;
+
+{
+ return (gss_verify(minor_status, (gss_ctx_id_t)context_handle,
+ (gss_buffer_t)message_buffer,
+ (gss_buffer_t)token_buffer, (int *) qop_state));
+}
diff --git a/usr/src/lib/libgss/gssd_pname_to_uid.c b/usr/src/lib/libgss/gssd_pname_to_uid.c
new file mode 100644
index 0000000000..f713bd3372
--- /dev/null
+++ b/usr/src/lib/libgss/gssd_pname_to_uid.c
@@ -0,0 +1,569 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <pwd.h>
+#include <grp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <thread.h>
+#include <synch.h>
+#include <syslog.h>
+#include <deflt.h>
+#include <mechglueP.h>
+#include "../../cmd/gss/gsscred/gsscred.h"
+
+static mutex_t uid_map_lock = DEFAULTMUTEX;
+static int uid_map_opt = 0;
+
+extern int _getgroupsbymember(const char *, gid_t[], int, int);
+
+/* local function used to call a mechanisms pname_to_uid */
+static OM_uint32 gss_pname_to_uid(OM_uint32*, const gss_name_t,
+ const gss_OID, uid_t *);
+
+static OM_uint32 private_gsscred_expname_to_unix_cred(const gss_buffer_t,
+ uid_t *, gid_t *, gid_t **, int *);
+
+/*
+ * The gsscred functions will first attempt to call the
+ * mechanism'm pname_to_uid function. In case this function
+ * returns an error or if it is not provided by a mechanism
+ * then the functions will attempt to look up the principal
+ * in the gsscred table.
+ * It is envisioned that the pname_to_uid function will be
+ * provided by only a few mechanism, which may have the principal
+ * name to unix credential mapping inherently present.
+ */
+
+/*
+ * Fetch gsscred options from conf file.
+ */
+static void
+get_conf_options(int *uid_map)
+{
+ register int flags;
+ char *ptr;
+ static char *conffile = "/etc/gss/gsscred.conf";
+ static mutex_t deflt_lock = DEFAULTMUTEX;
+
+
+ *uid_map = 0;
+ /*
+ * hold the lock for the deflt file access as its
+ * interface does not appear to be mt-safe
+ */
+ (void) mutex_lock(&deflt_lock);
+ if (defopen(conffile) == 0) {
+ flags = defcntl(DC_GETFLAGS, 0);
+ /* ignore case */
+ TURNOFF(flags, DC_CASE);
+ (void) defcntl(DC_SETFLAGS, flags);
+
+ if ((ptr = defread("SYSLOG_UID_MAPPING=")) != NULL &&
+ strcasecmp("yes", ptr) == 0) {
+ (void) defopen((char *)NULL);
+ (void) mutex_unlock(&deflt_lock);
+ *uid_map = 1;
+ return;
+ }
+ (void) defopen((char *)NULL);
+ }
+ (void) mutex_unlock(&deflt_lock);
+}
+
+void
+gsscred_set_options()
+{
+ int u;
+
+ get_conf_options(&u);
+ (void) mutex_lock(&uid_map_lock);
+ uid_map_opt = u;
+ (void) mutex_unlock(&uid_map_lock);
+}
+
+static int
+get_uid_map_opt()
+{
+ int u;
+
+ (void) mutex_lock(&uid_map_lock);
+ u = uid_map_opt;
+ (void) mutex_unlock(&uid_map_lock);
+ return (u);
+}
+
+/*
+ * This routine accepts a name in export name format and retrieves
+ * unix credentials associated with it.
+ */
+
+OM_uint32
+gsscred_expname_to_unix_cred_ext(
+ const gss_buffer_t expName,
+ uid_t *uidOut,
+ gid_t *gidOut,
+ gid_t *gids[],
+ int *gidsLen,
+ int try_mech)
+{
+ gss_name_t intName;
+ OM_uint32 minor, major;
+ const char *mechStr = NULL;
+ char *nameStr = NULL;
+ char *whoami = "gsscred_expname_to_unix_cred";
+ gss_buffer_desc namebuf;
+ int debug = get_uid_map_opt();
+
+ if (uidOut == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ if (expName == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ /* first check the mechanism for the mapping */
+ if (gss_import_name(&minor, expName, (gss_OID)GSS_C_NT_EXPORT_NAME,
+ &intName) == GSS_S_COMPLETE) {
+
+ if (debug) {
+ gss_union_name_t uintName = (gss_union_name_t)intName;
+
+ if (uintName->mech_type)
+ mechStr = __gss_oid_to_mech(
+ uintName->mech_type);
+
+ major = gss_display_name(&minor, intName,
+ &namebuf, NULL);
+ if (major == GSS_S_COMPLETE) {
+ nameStr = strdup(namebuf.value);
+ (void) gss_release_buffer(&minor, &namebuf);
+ }
+ }
+
+ if (try_mech) {
+ major = gss_pname_to_uid(&minor, intName,
+ NULL, uidOut);
+ if (major == GSS_S_COMPLETE) {
+
+ if (debug) {
+ syslog(LOG_AUTH|LOG_DEBUG,
+ "%s: mech provided local name"
+ " mapping (%s, %s, %d)", whoami,
+ mechStr ? mechStr : "<null>",
+ nameStr ? nameStr : "<null>",
+ *uidOut);
+ free(nameStr);
+ }
+
+ (void) gss_release_name(&minor, &intName);
+ if (gids && gidsLen && gidOut)
+ return (gss_get_group_info(*uidOut,
+ gidOut,
+ gids,
+ gidsLen));
+ return (GSS_S_COMPLETE);
+ }
+ }
+
+ (void) gss_release_name(&minor, &intName);
+ }
+
+ /*
+ * we fall back onto the gsscred table to provide the mapping
+ * start by making sure that the expName is an export name buffer
+ */
+ major = private_gsscred_expname_to_unix_cred(expName, uidOut, gidOut,
+ gids, gidsLen);
+
+ if (debug && major == GSS_S_COMPLETE) {
+ syslog(LOG_AUTH|LOG_DEBUG,
+ "%s: gsscred tbl provided"
+ " local name mapping (%s, %s, %d)",
+ whoami,
+ mechStr ? mechStr : "<unknown>",
+ nameStr ? nameStr : "<unknown>",
+ *uidOut);
+ free(nameStr);
+ } else if (debug) {
+ syslog(LOG_AUTH|LOG_DEBUG,
+ "%s: gsscred tbl could NOT"
+ " provide local name mapping (%s, %s)",
+ whoami,
+ mechStr ? mechStr : "<unknown>",
+ nameStr ? nameStr : "<unknown>");
+ free(nameStr);
+ }
+
+ return (major);
+
+} /* gsscred_expname_to_unix_cred */
+
+OM_uint32
+gsscred_expname_to_unix_cred(
+ const gss_buffer_t expName,
+ uid_t *uidOut,
+ gid_t *gidOut,
+ gid_t *gids[],
+ int *gidsLen)
+{
+ return (gsscred_expname_to_unix_cred_ext(expName, uidOut, gidOut, gids,
+ gidsLen, 1));
+}
+
+
+static const char *expNameTokId = "\x04\x01";
+static const int expNameTokIdLen = 2;
+/*
+ * private routine added to be called from gsscred_name_to_unix_cred
+ * and gsscred_expName_to_unix_cred.
+ */
+static OM_uint32
+private_gsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen)
+const gss_buffer_t expName;
+uid_t *uidOut;
+gid_t *gidOut;
+gid_t *gids[];
+int *gidsLen;
+{
+
+ if (expName->length < expNameTokIdLen ||
+ (memcmp(expName->value, expNameTokId, expNameTokIdLen) != 0))
+ return (GSS_S_DEFECTIVE_TOKEN);
+
+ if (!gss_getGssCredEntry(expName, uidOut))
+ return (GSS_S_FAILURE);
+
+ /* did caller request group info also ? */
+ if (gids && gidsLen && gidOut)
+ return (gss_get_group_info(*uidOut, gidOut, gids, gidsLen));
+
+ return (GSS_S_COMPLETE);
+}
+
+/*
+ * Return a string of the authenticated name.
+ * It's a bit of hack/workaround/longroad but the current intName
+ * passed to gss_display_name insists on returning an empty string.
+ *
+ * Caller must free string memory.
+ */
+static
+char *make_name_str(
+ const gss_name_t intName,
+ const gss_OID mechType)
+
+{
+ gss_buffer_desc expName = GSS_C_EMPTY_BUFFER;
+ OM_uint32 major, minor;
+ gss_name_t canonName;
+ gss_name_t iName;
+ gss_buffer_desc namebuf;
+
+ if (major = gss_canonicalize_name(&minor, intName,
+ mechType, &canonName))
+ return (NULL);
+
+ major = gss_export_name(&minor, canonName, &expName);
+ (void) gss_release_name(&minor, &canonName);
+ if (major)
+ return (NULL);
+
+ if (gss_import_name(&minor, &expName,
+ (gss_OID)GSS_C_NT_EXPORT_NAME,
+ &iName) == GSS_S_COMPLETE) {
+
+ major = gss_display_name(&minor, iName, &namebuf, NULL);
+ if (major == GSS_S_COMPLETE) {
+ char *s;
+
+ if (namebuf.value)
+ s = strdup(namebuf.value);
+
+ (void) gss_release_buffer(&minor, &namebuf);
+ (void) gss_release_buffer(&minor, &expName);
+ (void) gss_release_buffer(&minor, (gss_buffer_t)iName);
+ return (s);
+ }
+ (void) gss_release_buffer(&minor, (gss_buffer_t)iName);
+ }
+
+ (void) gss_release_buffer(&minor, &expName);
+ return (NULL);
+}
+
+/*
+ * This routine accepts a name in gss internal name format together with
+ * a mechanim OID and retrieves a unix credentials for that entity.
+ */
+OM_uint32
+gsscred_name_to_unix_cred_ext(
+ const gss_name_t intName,
+ const gss_OID mechType,
+ uid_t *uidOut,
+ gid_t *gidOut,
+ gid_t *gids[],
+ int *gidsLen,
+ int try_mech)
+{
+ gss_name_t canonName;
+ gss_buffer_desc expName = GSS_C_EMPTY_BUFFER;
+ OM_uint32 major, minor;
+ int debug = get_uid_map_opt();
+
+ const char *mechStr;
+ char *whoami = "gsscred_name_to_unix_cred";
+ gss_buffer_desc namebuf;
+
+ if (intName == NULL || mechType == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if (uidOut == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ mechStr = __gss_oid_to_mech(mechType);
+
+ /* first try the mechanism provided mapping */
+ if (try_mech && gss_pname_to_uid(&minor, intName, mechType, uidOut)
+ == GSS_S_COMPLETE) {
+
+ if (debug) {
+ char *s = make_name_str(intName, mechType);
+ syslog(LOG_AUTH|LOG_DEBUG,
+ "%s: mech provided local name"
+ " mapping (%s, %s, %d)", whoami,
+ mechStr ? mechStr : "<null>",
+ s ? s : "<null>",
+ *uidOut);
+ free(s);
+ }
+
+ if (gids && gidsLen && gidOut)
+ return (gss_get_group_info(*uidOut, gidOut, gids,
+ gidsLen));
+ return (GSS_S_COMPLETE);
+ }
+ /*
+ * falling back onto the gsscred table to provide the mapping
+ * start by canonicalizing the passed in name and then export it
+ */
+ if (major = gss_canonicalize_name(&minor, intName,
+ mechType, &canonName))
+ return (major);
+
+ major = gss_export_name(&minor, canonName, &expName);
+ (void) gss_release_name(&minor, &canonName);
+ if (major)
+ return (major);
+
+ major = private_gsscred_expname_to_unix_cred(&expName, uidOut, gidOut,
+ gids, gidsLen);
+
+
+ if (debug) {
+ gss_name_t iName;
+ OM_uint32 maj;
+ char *nameStr = NULL;
+
+ if (gss_import_name(&minor, &expName,
+ (gss_OID)GSS_C_NT_EXPORT_NAME,
+ &iName) == GSS_S_COMPLETE) {
+
+ maj = gss_display_name(&minor, iName, &namebuf,
+ NULL);
+ (void) gss_release_buffer(&minor, (gss_buffer_t)iName);
+ if (maj == GSS_S_COMPLETE) {
+ nameStr = strdup(namebuf.value);
+ (void) gss_release_buffer(&minor, &namebuf);
+ }
+ }
+
+ if (major == GSS_S_COMPLETE)
+ syslog(LOG_AUTH|LOG_DEBUG,
+ "%s: gsscred tbl provided"
+ " local name mapping (%s, %s, %d)",
+ whoami,
+ mechStr ? mechStr : "<unknown>",
+ nameStr ? nameStr : "<unknown>",
+ *uidOut);
+ else
+ syslog(LOG_AUTH|LOG_DEBUG,
+ "%s: gsscred tbl could NOT"
+ " provide local name mapping (%s, %s)",
+ whoami,
+ mechStr ? mechStr : "<unknown>",
+ nameStr ? nameStr : "<unknown>");
+
+ free(nameStr);
+ }
+
+ (void) gss_release_buffer(&minor, &expName);
+ return (major);
+} /* gsscred_name_to_unix_cred */
+
+
+OM_uint32
+gsscred_name_to_unix_cred(
+ const gss_name_t intName,
+ const gss_OID mechType,
+ uid_t *uidOut,
+ gid_t *gidOut,
+ gid_t *gids[],
+ int *gidsLen)
+{
+ return (gsscred_name_to_unix_cred_ext(intName, mechType,
+ uidOut, gidOut,
+ gids, gidsLen, 1));
+}
+
+
+
+/*
+ * This routine accepts a unix uid, and retrieves the group id
+ * and supplamentery group ids for that uid.
+ * Callers should be aware that the supplamentary group ids
+ * array may be empty even when this function returns success.
+ */
+OM_uint32
+gss_get_group_info(uid, gidOut, gids, gidsLen)
+const uid_t uid;
+gid_t *gidOut;
+gid_t *gids[];
+int *gidsLen;
+{
+ struct passwd *pw;
+ int maxgroups;
+
+ /* check for output parameters */
+ if (gidOut == NULL || gids == NULL || gidsLen == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *gids = NULL;
+ *gidsLen = 0;
+
+ /* determine maximum number of groups possible */
+ maxgroups = sysconf(_SC_NGROUPS_MAX);
+ if (maxgroups < 1)
+ maxgroups = 16;
+
+ if ((pw = getpwuid(uid)) == NULL)
+ return (GSS_S_FAILURE);
+
+ /*
+ * we allocate for the maximum number of groups
+ * we do not reclaim the space when the actual number
+ * is lower, just set the size approprately.
+ */
+ *gids = (gid_t *)calloc(maxgroups, sizeof (gid_t));
+ if (*gids == NULL)
+ return (GSS_S_FAILURE);
+
+ *gidOut = pw->pw_gid;
+ (*gids)[0] = pw->pw_gid;
+ *gidsLen = _getgroupsbymember(pw->pw_name, *gids, maxgroups, 1);
+ /*
+ * we will try to remove the duplicate entry from the groups
+ * array. This can cause the group array to be empty.
+ */
+ if (*gidsLen < 1)
+ {
+ free(*gids);
+ *gids = NULL;
+ return (GSS_S_FAILURE);
+ } else if (*gidsLen == 1) {
+ free(*gids);
+ *gids = NULL;
+ *gidsLen = 0;
+ } else {
+ /* length is atleast 2 */
+ *gidsLen = *gidsLen -1;
+ (*gids)[0] = (*gids)[*gidsLen];
+ }
+
+ return (GSS_S_COMPLETE);
+} /* gss_get_group_info */
+
+
+static OM_uint32
+gss_pname_to_uid(minor, name, mech_type, uidOut)
+OM_uint32 *minor;
+const gss_name_t name;
+const gss_OID mech_type;
+uid_t *uidOut;
+{
+ gss_mechanism mech;
+ gss_union_name_t intName;
+ gss_name_t mechName = NULL;
+ OM_uint32 major, tmpMinor;
+
+ if (!minor)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *minor = 0;
+
+ if (uidOut == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ if (name == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ intName = (gss_union_name_t)name;
+
+ if (mech_type != NULL)
+ mech = __gss_get_mechanism(mech_type);
+ else {
+ /*
+ * if this is a MN, then try using the mech
+ * from the name; otherwise ask for default
+ */
+ mech = __gss_get_mechanism(intName->mech_type);
+ }
+
+ if (mech == NULL || mech->pname_to_uid == NULL)
+ return (GSS_S_UNAVAILABLE);
+
+ /* may need to import the name if this is not MN */
+ if (intName->mech_type == NULL) {
+ major = __gss_import_internal_name(minor,
+ mech_type, intName,
+ &mechName);
+ if (major != GSS_S_COMPLETE)
+ return (major);
+ } else
+ mechName = intName->mech_name;
+
+
+ /* now call the mechanism's pname function to do the work */
+ major = mech->pname_to_uid(mech->context, minor, mechName, uidOut);
+
+ if (intName->mech_name != mechName)
+ (void) __gss_release_internal_name(&tmpMinor, &mech->mech_type,
+ &mechName);
+
+ return (major);
+} /* gss_pname_to_uid */
diff --git a/usr/src/lib/libgss/i386/Makefile b/usr/src/lib/libgss/i386/Makefile
new file mode 100644
index 0000000000..aacf5d2538
--- /dev/null
+++ b/usr/src/lib/libgss/i386/Makefile
@@ -0,0 +1,38 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libgss/i386/Makefile
+
+MAPDIR= ../spec/i386
+include ../Makefile.com
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
+
diff --git a/usr/src/lib/libgss/inc.flg b/usr/src/lib/libgss/inc.flg
new file mode 100644
index 0000000000..c3f65a4f15
--- /dev/null
+++ b/usr/src/lib/libgss/inc.flg
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+find_files "s.*.h" usr/src/uts/common/gssapi
+find_files "s.*.h" usr/src/cmd/gss/gsscred
diff --git a/usr/src/lib/libgss/llib-lgss b/usr/src/lib/libgss/llib-lgss
new file mode 100644
index 0000000000..b1756bb31a
--- /dev/null
+++ b/usr/src/lib/libgss/llib-lgss
@@ -0,0 +1,32 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* LINTLIBRARY */
+/* PROTOLIB1 */
+
+#include <gssapi/gssapi.h>
diff --git a/usr/src/lib/libgss/oid_ops.c b/usr/src/lib/libgss/oid_ops.c
new file mode 100644
index 0000000000..135b45deea
--- /dev/null
+++ b/usr/src/lib/libgss/oid_ops.c
@@ -0,0 +1,516 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * 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. 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 <mechglueP.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+
+/*
+ * this oid is defined in the oid structure but not exported to
+ * external callers; we must still ensure that we do not delete it.
+ */
+extern const gss_OID_desc * const gss_nt_service_name;
+
+
+OM_uint32
+generic_gss_release_oid(minor_status, oid)
+OM_uint32 *minor_status;
+gss_OID *oid;
+{
+ if (minor_status)
+ *minor_status = 0;
+
+ 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.
+ */
+
+ /*
+ * We use the official OID definitions instead of the unofficial OID
+ * defintions. But we continue to support the unofficial OID
+ * gss_nt_service_name just in case if some gss applications use
+ * the old OID.
+ */
+
+ 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) &&
+ (*oid != gss_nt_service_name)) {
+ free((*oid)->elements);
+ free(*oid);
+ }
+ *oid = GSS_C_NO_OID;
+ return (GSS_S_COMPLETE);
+}
+
+OM_uint32
+generic_gss_copy_oid(minor_status, oid, new_oid)
+ OM_uint32 *minor_status;
+ const gss_OID oid;
+ gss_OID *new_oid;
+{
+ gss_OID p;
+
+ if (minor_status)
+ *minor_status = 0;
+
+ p = (gss_OID) malloc(sizeof (gss_OID_desc));
+ if (!p) {
+ return (GSS_S_FAILURE);
+ }
+ p->length = oid->length;
+ p->elements = malloc(p->length);
+ if (!p->elements) {
+ free(p);
+ return (GSS_S_FAILURE);
+ }
+ (void) 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 (minor_status)
+ *minor_status = 0;
+
+ if ((*oid_set = (gss_OID_set) malloc(sizeof (gss_OID_set_desc)))) {
+ (void) memset(*oid_set, 0, sizeof (gss_OID_set_desc));
+ return (GSS_S_COMPLETE);
+ } else {
+ return (GSS_S_FAILURE);
+ }
+}
+
+OM_uint32
+generic_gss_add_oid_set_member(minor_status, member_oid, oid_set)
+OM_uint32 *minor_status;
+const gss_OID member_oid;
+gss_OID_set *oid_set;
+{
+ gss_OID elist;
+ gss_OID lastel;
+
+ if (minor_status)
+ *minor_status = 0;
+
+ if (member_oid == NULL || member_oid->length == 0 ||
+ member_oid->elements == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ 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)
+ (void) 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(member_oid->length))) {
+ /* Success - copy elements */
+ (void) memcpy(lastel->elements, member_oid->elements,
+ member_oid->length);
+ /* Set length */
+ lastel->length = member_oid->length;
+
+ /* Update count */
+ (*oid_set)->count++;
+ if (elist)
+ free(elist);
+ return (GSS_S_COMPLETE);
+ } else
+ free((*oid_set)->elements);
+ }
+ /* Failure - restore old contents of list */
+ (*oid_set)->elements = elist;
+ return (GSS_S_FAILURE);
+}
+
+OM_uint32
+generic_gss_test_oid_set_member(minor_status, member, set, present)
+ OM_uint32 *minor_status;
+ const gss_OID member;
+ const gss_OID_set set;
+ int *present;
+{
+ OM_uint32 i;
+ int result;
+
+ if (minor_status)
+ *minor_status = 0;
+
+ if (member == NULL || set == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if (present == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ result = 0;
+ for (i = 0; i < set->count; i++) {
+ if ((set->elements[i].length == member->length) &&
+ !memcmp(set->elements[i].elements,
+ member->elements, member->length)) {
+ result = 1;
+ break;
+ }
+ }
+ *present = result;
+ 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;
+const gss_OID oid;
+gss_buffer_t oid_str;
+{
+ char numstr[128];
+ OM_uint32 number;
+ int numshift;
+ OM_uint32 string_length;
+ OM_uint32 i;
+ unsigned char *cp;
+ char *bp;
+
+ if (minor_status)
+ *minor_status = 0;
+
+ if (oid == NULL || oid->length == 0 || oid->elements == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if (oid_str == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ /* 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 = (OM_uint32) cp[0];
+ (void) sprintf(numstr, "%d ", number/40);
+ string_length += strlen(numstr);
+ (void) sprintf(numstr, "%d ", number%40);
+ string_length += strlen(numstr);
+ for (i = 1; i < oid->length; i++) {
+ if ((OM_uint32) (numshift+7) < (sizeof (OM_uint32)*8)) {
+ number = (number << 7) | (cp[i] & 0x7f);
+ numshift += 7;
+ } else {
+ return (GSS_S_FAILURE);
+ }
+
+ if ((cp[i] & 0x80) == 0) {
+ (void) sprintf(numstr, "%d ", 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))) {
+ (void) strcpy(bp, "{ ");
+ number = (OM_uint32) cp[0];
+ (void) sprintf(numstr, "%d ", number/40);
+ (void) strcat(bp, numstr);
+ (void) sprintf(numstr, "%d ", number%40);
+ (void) 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) {
+ (void) sprintf(numstr, "%d ", number);
+ (void) strcat(bp, numstr);
+ number = 0;
+ }
+ }
+ (void) strcat(bp, "}");
+ oid_str->length = strlen(bp)+1;
+ oid_str->value = (void *) bp;
+ return (GSS_S_COMPLETE);
+ }
+ return (GSS_S_FAILURE);
+}
+
+/*
+ * This routine will handle 2 types of oid string formats:
+ * 1 - { 1 2 3 4 } where the braces are optional
+ * 2 - 1.2.3.4 this is an alernative format
+ * The first format is mandated by the gss spec. The
+ * second format is popular outside of the gss community so
+ * has been added.
+ */
+OM_uint32
+generic_gss_str_to_oid(minor_status, oid_str, oid)
+OM_uint32 *minor_status;
+const gss_buffer_t oid_str;
+gss_OID *oid;
+{
+ char *cp, *bp, *startp;
+ int brace;
+ int numbuf;
+ int onumbuf;
+ OM_uint32 nbytes;
+ int index;
+ unsigned char *op;
+
+ if (minor_status)
+ *minor_status = 0;
+
+ if (GSS_EMPTY_BUFFER(oid_str))
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if (oid == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ 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, "%d", &numbuf) != 1) {
+ return (GSS_S_FAILURE);
+ }
+ while ((bp < &cp[oid_str->length]) && isdigit(*bp))
+ bp++;
+ while ((bp < &cp[oid_str->length]) &&
+ (isspace(*bp) || *bp == '.'))
+ bp++;
+ if (sscanf(bp, "%d", &numbuf) != 1) {
+ return (GSS_S_FAILURE);
+ }
+ while ((bp < &cp[oid_str->length]) && isdigit(*bp))
+ bp++;
+ while ((bp < &cp[oid_str->length]) &&
+ (isspace(*bp) || *bp == '.'))
+ bp++;
+ nbytes++;
+ while (isdigit(*bp)) {
+ if (sscanf(bp, "%d", &numbuf) != 1) {
+ 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 == '.'))
+ bp++;
+ }
+ if (brace && (*bp != '}')) {
+ 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(nbytes))) {
+ (*oid)->length = nbytes;
+ op = (unsigned char *) (*oid)->elements;
+ bp = startp;
+ (void) sscanf(bp, "%d", &numbuf);
+ while (isdigit(*bp))
+ bp++;
+ while (isspace(*bp) || *bp == '.')
+ bp++;
+ onumbuf = 40*numbuf;
+ (void) sscanf(bp, "%d", &numbuf);
+ onumbuf += numbuf;
+ *op = (unsigned char) onumbuf;
+ op++;
+ while (isdigit(*bp))
+ bp++;
+ while (isspace(*bp) || *bp == '.')
+ bp++;
+ while (isdigit(*bp)) {
+ (void) sscanf(bp, "%d", &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 == '.')
+ bp++;
+ }
+ return (GSS_S_COMPLETE);
+ } else {
+ free(*oid);
+ *oid = GSS_C_NO_OID;
+ }
+ }
+ return (GSS_S_FAILURE);
+}
+
+/*
+ * 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.
+ */
+OM_uint32
+gss_copy_oid_set(
+ OM_uint32 *minor_status,
+ const gss_OID_set_desc * const oidset,
+ gss_OID_set *new_oidset
+)
+{
+ gss_OID_set_desc *copy;
+ OM_uint32 minor = 0;
+ OM_uint32 major = GSS_S_COMPLETE;
+ OM_uint32 index;
+
+ if (minor_status)
+ *minor_status = 0;
+
+ if (oidset == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_READ);
+
+ if (new_oidset == NULL)
+ return (GSS_S_CALL_INACCESSIBLE_WRITE);
+
+ *new_oidset = NULL;
+
+ if ((copy = (gss_OID_set_desc *) calloc(1, sizeof (*copy))) == NULL) {
+ major = GSS_S_FAILURE;
+ goto done;
+ }
+
+ if ((copy->elements = (gss_OID_desc *)
+ calloc(oidset->count, sizeof (*copy->elements))) == NULL) {
+ major = GSS_S_FAILURE;
+ goto done;
+ }
+ copy->count = oidset->count;
+
+ for (index = 0; index < copy->count; index++) {
+ gss_OID_desc *out = &copy->elements[index];
+ gss_OID_desc *in = &oidset->elements[index];
+
+ if ((out->elements = (void *) malloc(in->length)) == NULL) {
+ major = GSS_S_FAILURE;
+ goto done;
+ }
+ (void) memcpy(out->elements, in->elements, in->length);
+ out->length = in->length;
+ }
+
+ *new_oidset = copy;
+done:
+ if (major != GSS_S_COMPLETE) {
+ (void) gss_release_oid_set(&minor, &copy);
+ }
+
+ return (major);
+}
diff --git a/usr/src/lib/libgss/req.flg b/usr/src/lib/libgss/req.flg
new file mode 100644
index 0000000000..3910349402
--- /dev/null
+++ b/usr/src/lib/libgss/req.flg
@@ -0,0 +1,31 @@
+#!/bin/sh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+echo_file usr/src/cmd/gss/gsscred/gsscred_file.c
+echo_file usr/src/cmd/gss/gsscred/gsscred_utils.c
+echo_file usr/src/uts/common/gssapi/gen_oids.c
diff --git a/usr/src/lib/libgss/sparc/Makefile b/usr/src/lib/libgss/sparc/Makefile
new file mode 100644
index 0000000000..fe210b036e
--- /dev/null
+++ b/usr/src/lib/libgss/sparc/Makefile
@@ -0,0 +1,37 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 1997-2003 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libgss/sparc/Makefile
+
+MAPDIR= ../spec/sparc
+include ../Makefile.com
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libgss/sparcv9/Makefile b/usr/src/lib/libgss/sparcv9/Makefile
new file mode 100644
index 0000000000..a4095ab7ce
--- /dev/null
+++ b/usr/src/lib/libgss/sparcv9/Makefile
@@ -0,0 +1,38 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libgss/sparcv9/Makefile
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+GSSMECH_DIR_V9 = $(ROOT)/usr/lib/sparcv9/gss
+
+install: all $(GSSMECH_DIR_V9) $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
+
+$(GSSMECH_DIR_V9):
+ $(INS.dir)
diff --git a/usr/src/lib/libgss/spec/Makefile b/usr/src/lib/libgss/spec/Makefile
new file mode 100644
index 0000000000..7a3f89b118
--- /dev/null
+++ b/usr/src/lib/libgss/spec/Makefile
@@ -0,0 +1,30 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 1997-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libgss/spec/Makefile
+
+include $(SRC)/lib/Makefile.spec.arch
diff --git a/usr/src/lib/libgss/spec/Makefile.targ b/usr/src/lib/libgss/spec/Makefile.targ
new file mode 100644
index 0000000000..ce18aa182d
--- /dev/null
+++ b/usr/src/lib/libgss/spec/Makefile.targ
@@ -0,0 +1,36 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 1997-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libgss/spec/Makefile.targ
+
+LIBRARY = libgss.a
+VERS = .1
+
+OBJECTS = gss.o
+
+TRANSCPP =
+SPECCPP =
diff --git a/usr/src/lib/libgss/spec/amd64/Makefile b/usr/src/lib/libgss/spec/amd64/Makefile
new file mode 100644
index 0000000000..2a38c1cba9
--- /dev/null
+++ b/usr/src/lib/libgss/spec/amd64/Makefile
@@ -0,0 +1,42 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+
+# Uncomment the following if the linker complains
+#amd64_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB64)
diff --git a/usr/src/lib/libgss/spec/gss.spec b/usr/src/lib/libgss/spec/gss.spec
new file mode 100644
index 0000000000..6cfae0c489
--- /dev/null
+++ b/usr/src/lib/libgss/spec/gss.spec
@@ -0,0 +1,753 @@
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libgss/spec/gss.spec
+
+data GSS_C_NT_USER_NAME
+version SUNW_1.2
+end
+
+data GSS_C_NT_MACHINE_UID_NAME
+version SUNW_1.2
+end
+
+data GSS_C_NT_STRING_UID_NAME
+version SUNW_1.2
+end
+
+data GSS_C_NT_HOSTBASED_SERVICE
+version SUNW_1.2
+end
+
+data GSS_C_NT_ANONYMOUS
+version SUNW_1.2
+end
+
+data GSS_C_NT_EXPORT_NAME
+version SUNW_1.2
+end
+
+function gss_release_oid_set
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_release_oid_set( \
+ OM_uint32 *minor_status ,\
+ gss_OID_set *set)
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_acquire_cred
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_acquire_cred( \
+ OM_uint32 *minor_status ,\
+ const gss_name_t desired_name ,\
+ OM_uint32 time_req ,\
+ const gss_OID_set desired_mechs ,\
+ gss_cred_usage_t cred_usage ,\
+ gss_cred_id_t *output_cred_handle ,\
+ gss_OID_set *actual_mechs ,\
+ OM_uint32 *time_rec)
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_acquire_cred_with_password
+include <gssapi/gssapi_ext.h>
+declaration OM_uint32 gss_acquire_cred_with_password( \
+ OM_uint32 *minor_status ,\
+ const gss_name_t desired_name ,\
+ const gss_buffer_t password ,\
+ OM_uint32 time_req ,\
+ const gss_OID_set desired_mechs ,\
+ gss_cred_usage_t cred_usage ,\
+ gss_cred_id_t *output_cred_handle ,\
+ gss_OID_set *actual_mechs ,\
+ OM_uint32 *time_rec)
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_release_cred
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_release_cred( \
+ OM_uint32 * minor_status,\
+ gss_cred_id_t * cred_handle \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_init_sec_context
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_init_sec_context( \
+ OM_uint32 * minor_status ,\
+ const gss_cred_id_t initiator_cred_hdle,\
+ gss_ctx_id_t * context_handle ,\
+ const gss_name_t target_name ,\
+ const gss_OID mech_type ,\
+ OM_uint32 req_flags ,\
+ OM_uint32 time_req ,\
+ gss_channel_bindings_t input_chan_bindings ,\
+ const gss_buffer_t input_token ,\
+ gss_OID * actual_mech_type ,\
+ gss_buffer_t output_token ,\
+ OM_uint32 * ret_flags ,\
+ OM_uint32 * time_rec \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_accept_sec_context
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_accept_sec_context( \
+ OM_uint32 * minor_status ,\
+ gss_ctx_id_t * context_handle ,\
+ const gss_cred_id_t acceptor_cred_hdle ,\
+ const gss_buffer_t input_token_buffer ,\
+ const 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_hdle \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_process_context_token
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_process_context_token( \
+ OM_uint32 * minor_status ,\
+ const gss_ctx_id_t context_handle ,\
+ const gss_buffer_t token_buffer \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_delete_sec_context
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_delete_sec_context( \
+ OM_uint32 * minor_status ,\
+ gss_ctx_id_t * context_handle ,\
+ gss_buffer_t output_token \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_context_time
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_context_time( \
+ OM_uint32 * minor_status ,\
+ const gss_ctx_id_t context_handle ,\
+ OM_uint32 * time_rec \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_display_status
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_display_status( \
+ OM_uint32 * minor_status ,\
+ OM_uint32 status_value ,\
+ int status_type ,\
+ const gss_OID mech_type ,\
+ OM_uint32 * message_context ,\
+ gss_buffer_t status_string \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_indicate_mechs
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_indicate_mechs( \
+ OM_uint32 * minor_status ,\
+ gss_OID_set * mech_set \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_compare_name
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_compare_name( \
+ OM_uint32 * minor_status ,\
+ const gss_name_t name1 ,\
+ const gss_name_t name2 ,\
+ int * name_equal \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_display_name
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_display_name( \
+ OM_uint32 * minor_status ,\
+ const gss_name_t input_name ,\
+ gss_buffer_t output_name_buffer ,\
+ gss_OID * output_name_type \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_import_name
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_import_name( \
+ OM_uint32 * minor_status ,\
+ const gss_buffer_t input_name_buffer ,\
+ const gss_OID input_name_type ,\
+ gss_name_t * output_name \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_release_name
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_release_name( \
+ OM_uint32 * minor_status ,\
+ gss_name_t * input_name \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_release_buffer
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_release_buffer( \
+ OM_uint32 * minor_status ,\
+ gss_buffer_t buffer \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+
+function gss_inquire_cred
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_inquire_cred( \
+ OM_uint32 * minor_status ,\
+ const gss_cred_id_t cred_handle ,\
+ gss_name_t * name ,\
+ OM_uint32 * lifetime ,\
+ gss_cred_usage_t * cred_usage ,\
+ gss_OID_set * mechanisms \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_inquire_context
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_inquire_context( \
+ OM_uint32 * minor_status ,\
+ const 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 \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_get_mic
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_get_mic( \
+ OM_uint32 * minor_status ,\
+ const gss_ctx_id_t context_handle ,\
+ gss_qop_t qop_req ,\
+ const gss_buffer_t message_buffer ,\
+ gss_buffer_t message_token \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_verify_mic
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_verify_mic( \
+ OM_uint32 * minor_status ,\
+ const gss_ctx_id_t context_handle ,\
+ const gss_buffer_t message_buffer ,\
+ const gss_buffer_t token_buffer ,\
+ gss_qop_t * qop_state \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_wrap
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_wrap( \
+ OM_uint32 * minor_status ,\
+ const gss_ctx_id_t context_handle ,\
+ int conf_req_flag ,\
+ gss_qop_t qop_req ,\
+ const gss_buffer_t input_message_bfer ,\
+ int * conf_state ,\
+ gss_buffer_t output_message_bfer \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_unwrap
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_unwrap( \
+ OM_uint32 * minor_status ,\
+ const gss_ctx_id_t context_handle ,\
+ const gss_buffer_t input_message_bfer ,\
+ gss_buffer_t output_message_bfer ,\
+ int * conf_state ,\
+ gss_qop_t * qop_state \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_wrap_size_limit
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_wrap_size_limit( \
+ OM_uint32 * minor_status ,\
+ const 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 \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_export_name
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_export_name( \
+ OM_uint32 * minor_status ,\
+ const gss_name_t input_name ,\
+ gss_buffer_t exported_name \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_add_cred
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_add_cred( \
+ OM_uint32 * minor_status ,\
+ const gss_cred_id_t input_cred_handle ,\
+ const gss_name_t desired_name ,\
+ const 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 \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_add_cred_with_password
+include <gssapi/gssapi_ext.h>
+declaration OM_uint32 gss_add_cred_with_password( \
+ OM_uint32 * minor_status ,\
+ const gss_cred_id_t input_cred_handle ,\
+ const gss_name_t desired_name ,\
+ const gss_OID desired_mech ,\
+ const gss_buffer_t password ,\
+ 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 \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_store_cred
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_store_cred( \
+ OM_uint32 * minor_status ,\
+ const gss_cred_id_t input_cred_handle ,\
+ gss_cred_usage_t cred_usage ,\
+ const gss_OID desired_mech ,\
+ OM_uint32 overwrite_cred ,\
+ OM_uint32 default_cred ,\
+ gss_OID_set * elements_stored ,\
+ gss_cred_usage_t * cred_usage_stored \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_inquire_cred_by_mech
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_inquire_cred_by_mech( \
+ OM_uint32 * minor_status ,\
+ const gss_cred_id_t cred_handle ,\
+ const gss_OID mech_type ,\
+ gss_name_t * name ,\
+ OM_uint32 * initiator_lifetime ,\
+ OM_uint32 * acceptor_lifetime ,\
+ gss_cred_usage_t * cred_usage \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_export_sec_context
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_export_sec_context( \
+ OM_uint32 * minor_status ,\
+ gss_ctx_id_t * context_handle ,\
+ gss_buffer_t interprocess_token \
+)
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_import_sec_context
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_import_sec_context( \
+ OM_uint32 * minor_status ,\
+ const gss_buffer_t interprocess_token ,\
+ gss_ctx_id_t * context_handle \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_release_oid
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_release_oid( \
+ OM_uint32 * minor_status ,\
+ gss_OID * oid \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_create_empty_oid_set
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_create_empty_oid_set( \
+ OM_uint32 * minor_status ,\
+ gss_OID_set * oid_set \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_add_oid_set_member
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_add_oid_set_member( \
+ OM_uint32 * minor_status ,\
+ const gss_OID member_oid ,\
+ gss_OID_set * oid_set \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_test_oid_set_member
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_test_oid_set_member( \
+ OM_uint32 * minor_status ,\
+ const gss_OID member ,\
+ const gss_OID_set set ,\
+ int *present)
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_str_to_oid
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_str_to_oid( \
+ OM_uint32 * minor_status ,\
+ const gss_buffer_t oid_str ,\
+ gss_OID * oid \
+ )
+version SUNWprivate_1.1
+exception $return != 0
+end
+
+
+function gss_inquire_names_for_mech
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_inquire_names_for_mech( \
+ OM_uint32 * minor_status ,\
+ const gss_OID mechanism ,\
+ gss_OID_set * name_types \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_inquire_mechs_for_name
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_inquire_mechs_for_name( \
+ OM_uint32 * minor_status ,\
+ const gss_name_t input_name ,\
+ gss_OID_set * mech_types \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_canonicalize_name
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_canonicalize_name( \
+ OM_uint32 * minor_status ,\
+ const gss_name_t input_name ,\
+ const gss_OID mech_type ,\
+ gss_name_t * output_name \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_duplicate_name
+include <gssapi/gssapi.h>
+declaration OM_uint32 gss_duplicate_name( \
+ OM_uint32 * minor_status ,\
+ const gss_name_t src_name ,\
+ gss_name_t * dest_name \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_sign
+declaration OM_uint32 gss_sign(OM_uint32 *minor_status ,\
+ gss_ctx_id_t context_handle ,\
+ int qop_req,\
+ gss_buffer_t message_buffer ,\
+ gss_buffer_t message_token \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_verify
+declaration OM_uint32 gss_verify( \
+ OM_uint32 *minor_status ,\
+ gss_ctx_id_t context_handle ,\
+ gss_buffer_t message_buffer ,\
+ gss_buffer_t token_buffer,\
+ int *qop_state \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_seal
+declaration OM_uint32 gss_seal( \
+ OM_uint32 *minor_status ,\
+ gss_ctx_id_t context_handle ,\
+ int conf_req_flag ,\
+ int qop_req ,\
+ gss_buffer_t input_message_bfer ,\
+ int *conf_state ,\
+ gss_buffer_t output_message_bfer \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_unseal
+declaration OM_uint32 gss_unseal( \
+ OM_uint32 *minor_status ,\
+ gss_ctx_id_t context_handle ,\
+ gss_buffer_t input_message_bfer ,\
+ gss_buffer_t output_message_bfer ,\
+ int *conf_state ,\
+ int *qop_state \
+ )
+version SUNW_1.2
+exception $return != 0
+end
+
+function gss_oid_to_str
+version SUNWprivate_1.1
+end
+
+function gss_copy_oid_set
+declaration OM_uint32 gss_copy_oid_set( \
+ OM_uint32 *,\
+ const gss_OID_set_desc *, \
+ gss_OID_set *)
+version SUNWprivate_1.1
+end
+
+data gss_nt_exported_name
+declaration const gss_OID_desc * const gss_nt_exported_name;
+version SUNWprivate_1.1
+end
+
+data gss_nt_service_name
+declaration const gss_OID_desc * const gss_nt_service_name;
+version SUNWprivate_1.1
+end
+
+data gss_nt_service_name_v2
+declaration const gss_OID_desc * const gss_nt_service_name_v2;
+version SUNWprivate_1.1
+end
+
+function __gss_qop_to_num
+version SUNWprivate_1.1
+end
+
+function __gss_num_to_qop
+version SUNWprivate_1.1
+end
+
+function __gss_get_mech_info
+version SUNWprivate_1.1
+end
+
+function __gss_mech_qops
+version SUNWprivate_1.1
+end
+
+function __gss_mech_to_oid
+version SUNWprivate_1.1
+end
+
+function __gss_oid_to_mech
+version SUNWprivate_1.1
+end
+
+function __gss_get_mechanisms
+version SUNWprivate_1.1
+end
+
+function __gss_userok
+declaration OM_uint32 __gss_userok(\
+ OM_uint32 *minor,\
+ const gss_name_t name,\
+ const char *user,\
+ int *user_ok)
+version SUNWprivate_1.1
+end
+
+function gsscred_expname_to_unix_cred
+version SUNWprivate_1.1
+end
+
+function gsscred_expname_to_unix_cred_ext
+declaration OM_uint32 gsscred_expname_to_unix_cred_ext(\
+ const gss_buffer_t expName,\
+ uid_t *uidOut,\
+ gid_t *gidOut,\
+ gid_t *gids[],\
+ int *gidsLen,\
+ int try_mech)
+version SUNWprivate_1.1
+end
+
+function gsscred_name_to_unix_cred
+declaration OM_uint32 gsscred_name_to_unix_cred( \
+ const gss_name_t intName, \
+ const gss_OID mechType, \
+ uid_t *uidOut, \
+ gid_t *gidOut, \
+ gid_t *gids[], \
+ int *gidsLen)
+version SUNWprivate_1.1
+end
+
+function gsscred_name_to_unix_cred_ext
+declaration OM_uint32 gsscred_name_to_unix_cred_ext(\
+ const gss_name_t intName,\
+ const gss_OID mechType,\
+ uid_t *uidOut,\
+ gid_t *gidOut,\
+ gid_t *gids[],\
+ int *gidsLen,\
+ int try_mech)
+version SUNWprivate_1.1
+end
+
+function gsscred_set_options
+declaration void gsscred_set_options(void)
+version SUNWprivate_1.1
+end
+
+function gss_get_group_info
+version SUNWprivate_1.1
+end
+
+function __gss_get_modOptions
+declaration char * __gss_get_modOptions(const gss_OID)
+version SUNWprivate_1.1
+end
+
+function __gss_get_kmodName
+version SUNWprivate_1.1
+end
+
+# Needed by mech_dummy.so to run rpcgss_sample with -m 2
+function generic_gss_copy_oid
+version SUNWprivate_1.1
+end
+
+# Needed by mech_dummy.so to run rpcgss_sample with -m 2
+function generic_gss_release_oid
+version SUNWprivate_1.1
+end
+
+function __gss_get_mech_type
+version SUNWprivate_1.1
+end
+
+function der_length_size
+version SUNWprivate_1.1
+end
+
+function get_der_length
+version SUNWprivate_1.1
+end
+
+function put_der_length
+version SUNWprivate_1.1
+end
diff --git a/usr/src/lib/libgss/spec/i386/Makefile b/usr/src/lib/libgss/spec/i386/Makefile
new file mode 100644
index 0000000000..401acdcae1
--- /dev/null
+++ b/usr/src/lib/libgss/spec/i386/Makefile
@@ -0,0 +1,42 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 1997-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libgss/spec/i386/Makefile
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+
+# Uncomment the following if the linker complains
+#i386_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB)
diff --git a/usr/src/lib/libgss/spec/sparc/Makefile b/usr/src/lib/libgss/spec/sparc/Makefile
new file mode 100644
index 0000000000..1af31f36a2
--- /dev/null
+++ b/usr/src/lib/libgss/spec/sparc/Makefile
@@ -0,0 +1,44 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 1997-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libgss/spec/sparc/Makefile
+
+.KEEP_STATE:
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+
+# Uncomment the following if the linker complains
+#sparc_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB)
diff --git a/usr/src/lib/libgss/spec/sparcv9/Makefile b/usr/src/lib/libgss/spec/sparcv9/Makefile
new file mode 100644
index 0000000000..1eb81d037c
--- /dev/null
+++ b/usr/src/lib/libgss/spec/sparcv9/Makefile
@@ -0,0 +1,43 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 1997-1999 by Sun Microsystems, Inc.
+# All rights reserved.
+#
+#pragma ident "%Z%%M% %I% %E% SMI"
+#
+# lib/libgss/spec/sparcv9/Makefile
+
+include ../Makefile.targ
+
+# Add arch specific objects here
+OBJECTS +=
+
+include $(SRC)/lib/Makefile.lib
+include $(SRC)/lib/Makefile.lib.64
+
+# Uncomment the following if the linker complains
+#sparcv9_C_PICFLAGS = -K PIC
+
+include $(SRC)/lib/Makefile.spec
+
+install: $(ROOTABILIB64)
diff --git a/usr/src/lib/libgss/spec/versions b/usr/src/lib/libgss/spec/versions
new file mode 100644
index 0000000000..5fa1ed3b51
--- /dev/null
+++ b/usr/src/lib/libgss/spec/versions
@@ -0,0 +1,47 @@
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+sparc {
+ SUNW_1.2: {SUNW_1.1};
+ SUNW_1.1;
+ SUNWprivate_1.1;
+}
+sparcv9 {
+ SUNW_1.2: {SUNW_1.1};
+ SUNW_1.1;
+ SUNWprivate_1.1;
+}
+i386 {
+ SUNW_1.2: {SUNW_1.1};
+ SUNW_1.1;
+ SUNWprivate_1.1;
+}
+amd64 {
+ SUNW_1.2: {SUNW_1.1};
+ SUNW_1.1;
+ SUNWprivate_1.1;
+}