diff options
author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
---|---|---|
committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/lib/libgss | |
download | illumos-gate-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz |
OpenSolaris Launch
Diffstat (limited to 'usr/src/lib/libgss')
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 = ©->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, ©); + } + + 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; +} |