diff options
| author | Glenn Barry <Glenn.Barry@Sun.COM> | 2009-09-21 16:47:51 -0700 |
|---|---|---|
| committer | Glenn Barry <Glenn.Barry@Sun.COM> | 2009-09-21 16:47:51 -0700 |
| commit | ba7b222e36bac28710a7f43739283302b617e7f5 (patch) | |
| tree | f864f6d889ae7a00f9b8c9577cc94f7dff53e1c2 /usr/src/lib/libgss | |
| parent | 22edf370974e46eb43b66530dd2d862b0d0a9533 (diff) | |
| download | illumos-joyent-ba7b222e36bac28710a7f43739283302b617e7f5.tar.gz | |
PSARC 2009/418 Kerberos V5 PAC API
6283931 SPNEGO needs to follow latest RFC
6808598 krb5 APIs needed to create and parse PAC data
6817447 libgss and various mechs are hiding both the real minor_status and the error token
Diffstat (limited to 'usr/src/lib/libgss')
| -rw-r--r-- | usr/src/lib/libgss/Makefile.com | 30 | ||||
| -rw-r--r-- | usr/src/lib/libgss/g_accept_sec_context.c | 13 | ||||
| -rw-r--r-- | usr/src/lib/libgss/g_buffer_set.c | 62 | ||||
| -rw-r--r-- | usr/src/lib/libgss/g_glue.c | 1039 | ||||
| -rw-r--r-- | usr/src/lib/libgss/g_inq_context_oid.c | 77 | ||||
| -rw-r--r-- | usr/src/lib/libgss/mapfile-vers | 6 |
6 files changed, 760 insertions, 467 deletions
diff --git a/usr/src/lib/libgss/Makefile.com b/usr/src/lib/libgss/Makefile.com index a14b9a5810..46fbd4c810 100644 --- a/usr/src/lib/libgss/Makefile.com +++ b/usr/src/lib/libgss/Makefile.com @@ -19,11 +19,9 @@ # CDDL HEADER END # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# LIBRARY = libgss.a VERS = .1 @@ -62,20 +60,29 @@ GSSOBJECTS = g_acquire_cred.o \ g_dup_name.o \ g_export_name.o \ g_utils.o \ - g_userok.o + g_userok.o \ + g_buffer_set.o \ + g_inq_context_oid.o \ # defines the duplicate sources we share with gsscred GSSCRED_DIR = $(SRC)/cmd/gss/gsscred GSSCREDOBJ = gsscred_utils.o gsscred_file.o +# defines the duplicate sources we share with krb5 mech +KRB5DIR= $(SRC)/lib/gss_mechs/mech_krb5/mech +KRB5OBJ= rel_buffer.o util_buffer_set.o +# defines the duplicate sources we share with kernel module UTSGSSDIR = $(SRC)/uts/common/gssapi UTSGSSOBJ = gen_oids.o + SRCS += $(GSSCREDOBJ:%.o=$(GSSCRED_DIR)/%.c) \ + $(KRB5OBJ:%.o=$(KRB5DIR)/%.c) \ $(UTSGSSOBJ:%.o=$(UTSGSSDIR)/%.c) GSSLINTSRC = $(GSSOBJECTS:%.o=$(SRCDIR)/%.c) \ $(GSSCREDOBJ:%.o=$(GSSCRED_DIR)/%.c) \ + $(KRB5OBJ:%.o=$(KRB5DIR)/%.c) \ $(UTSGSSOBJ:%.o=$(UTSGSSDIR)/%.c) -OBJECTS = $(GSSOBJECTS) $(GSSCREDOBJ) $(UTSGSSOBJ) +OBJECTS = $(GSSOBJECTS) $(GSSCREDOBJ) $(KRB5OBJ) $(UTSGSSOBJ) # include library definitions include ../../Makefile.lib @@ -86,6 +93,9 @@ $(LINTLIB):= SRCS = $(SRCDIR)/$(LINTSRC) LDLIBS += -lc CPPFLAGS += -I$(GSSCRED_DIR) -I$(SRC)/uts/common/gssapi/include \ + -I$(SRC)/uts/common/gssapi/mechs/krb5/include \ + -I$(SRC)/uts/common/gssapi/ \ + -I$(SRC)/lib/gss_mechs/mech_krb5/include/ \ -DHAVE_STDLIB_H $(EXPORT_RELEASE_BUILD)include $(CLOSED)/lib/libgss/Makefile.export @@ -102,6 +112,16 @@ $(GSSCREDOBJ:%.o=pics/%.o): $(COMPILE.c) -o $@ $(@:pics/%.o=$(GSSCRED_DIR)/%.c) $(POST_PROCESS_O) +# we need this in libgss so we don't have to link against mech_krb5 +pics/rel_buffer.o: $(SRC)/lib/gss_mechs/mech_krb5/mech/rel_buffer.c + $(COMPILE.c) -o $@ $(SRC)/lib/gss_mechs/mech_krb5/mech/rel_buffer.c + $(POST_PROCESS_O) + +# we need this in libgss so we don't have to link against mech_krb5 +pics/util_buffer_set.o: $(SRC)/lib/gss_mechs/mech_krb5/mech/util_buffer_set.c + $(COMPILE.c) -o $@ $(SRC)/lib/gss_mechs/mech_krb5/mech/util_buffer_set.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 diff --git a/usr/src/lib/libgss/g_accept_sec_context.c b/usr/src/lib/libgss/g_accept_sec_context.c index 79b092ef9d..2acb9c7172 100644 --- a/usr/src/lib/libgss/g_accept_sec_context.c +++ b/usr/src/lib/libgss/g_accept_sec_context.c @@ -2,9 +2,8 @@ * 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. + * Common Development and Distribution License (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. @@ -140,7 +139,7 @@ gss_cred_id_t *d_cred; /* delegated cred handle */ if (*context_handle == GSS_C_NO_CONTEXT) { - if (GSS_EMPTY_BUFFER(input_token_buffer)) + if (input_token_buffer == GSS_C_NO_BUFFER) return (GSS_S_CALL_INACCESSIBLE_READ); /* Get the token mech type */ @@ -365,8 +364,14 @@ error_out: *context_handle = GSS_C_NO_CONTEXT; } +#if 0 + /* + * Solaris Kerberos + * Don't release, it causes a problem with error token. + */ if (output_token->length) (void) gss_release_buffer(&t_minstat, output_token); +#endif if (src_name) *src_name = GSS_C_NO_NAME; diff --git a/usr/src/lib/libgss/g_buffer_set.c b/usr/src/lib/libgss/g_buffer_set.c new file mode 100644 index 0000000000..1788307531 --- /dev/null +++ b/usr/src/lib/libgss/g_buffer_set.c @@ -0,0 +1,62 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +#include "mglueP.h" +#include <stdio.h> +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif +#include <string.h> +#include <errno.h> + +OM_uint32 gss_create_empty_buffer_set + (OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set) +{ + return generic_gss_create_empty_buffer_set(minor_status, buffer_set); +} + +OM_uint32 gss_add_buffer_set_member + (OM_uint32 * minor_status, + const gss_buffer_t member_buffer, + gss_buffer_set_t *buffer_set) +{ + return generic_gss_add_buffer_set_member(minor_status, + member_buffer, + buffer_set); +} + +OM_uint32 gss_release_buffer_set + (OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set) +{ + return generic_gss_release_buffer_set(minor_status, buffer_set); +} + diff --git a/usr/src/lib/libgss/g_glue.c b/usr/src/lib/libgss/g_glue.c index e402dc67b8..49ece2fd35 100644 --- a/usr/src/lib/libgss/g_glue.c +++ b/usr/src/lib/libgss/g_glue.c @@ -1,38 +1,44 @@ /* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (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 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +#include "mglueP.h" -#include <mechglueP.h> #include <stdio.h> +#ifdef HAVE_STDLIB_H #include <stdlib.h> -#include <strings.h> +#endif +#include <string.h> #include <errno.h> +#include "k5-platform-store_32.h" +#include "k5-platform-store_16.h" +/* + * SUNW17PACresync + * MIT has diff names for these GSS utilities. Solaris needs to change + * them globally to get in sync w/MIT. + * Revisit for full 1.7 resync. + */ +#define gssint_get_modOptions __gss_get_modOptions +#define gssint_der_length_size der_length_size +#define gssint_get_der_length get_der_length +#define gssint_put_der_length put_der_length +#define gssint_get_mechanism __gss_get_mechanism +#define gssint_get_mechanism_cred __gss_get_mechanism_cred +#define gssint_copy_oid_set gss_copy_oid_set +#define gssint_get_mech_type __gss_get_mech_type +#define gssint_export_internal_name __gss_export_internal_name +#define gssint_release_internal_name __gss_release_internal_name +#define gssint_convert_name_to_union_name __gss_convert_name_to_union_name +#define gssint_import_internal_name __gss_import_internal_name +#define gssint_display_internal_name __gss_display_internal_name + + #define MSO_BIT (8*(sizeof (int) - 1)) /* Most significant octet bit */ +extern gss_mechanism *gssint_mechs_array; + /* * This file contains the support routines for the glue layer. */ @@ -45,72 +51,72 @@ * by the buffer. Note we return -1 on error. */ int -get_der_length(unsigned char **buf, unsigned int buf_len, unsigned int *bytes) +gssint_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 */ + /* p points to the beginning of the buffer */ + unsigned char *p = *buf; + int length, new_length; + unsigned 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); + } + + /* + * 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) +gssint_der_length_size(unsigned int len) { - int i; + int i; - if (len < 128) - return (1); + if (len < 128) + return (1); - for (i = 0; len; i++) { - len >>= 8; - } + for (i = 0; len; i++) { + len >>= 8; + } - return (i+1); + return (i+1); } /* @@ -121,58 +127,60 @@ der_length_size(unsigned int len) * be encoded in max_len characters. */ int -put_der_length(unsigned length, unsigned char **buf, unsigned int max_len) +gssint_put_der_length(unsigned int 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); - } + unsigned char *s, *p; + unsigned int buf_len = 0; + int i, first; - /* 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); + /* Oops */ + if (buf == 0 || max_len < 1) + 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; + s = *buf; + /* 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); } @@ -180,342 +188,433 @@ put_der_length(unsigned length, unsigned char **buf, unsigned int max_len) * 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. - */ +OM_uint32 gssint_get_mech_type_oid(OID, token) + gss_OID OID; + gss_buffer_t token; +{ + unsigned char * buffer_ptr; + int length; + + /* + * This routine reads the prefix of "token" in order to determine + * its mechanism type. It assumes the encoding suggested in + * Appendix B of RFC 1508. This format starts out as follows : + * + * tag for APPLICATION 0, Sequence[constructed, definite length] + * length of remainder of token + * tag of OBJECT IDENTIFIER + * length of mechanism OID + * encoding of mechanism OID + * <the rest of the token> + * + * Numerically, this looks like : + * + * 0x60 + * <length> - could be multiple bytes + * 0x06 + * <length> - assume only one byte, hence OID length < 127 + * <mech OID bytes> + * + * The routine fills in the OID value and returns an error as necessary. + */ + if (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 */ + return (GSS_S_DEFECTIVE_TOKEN); + + /* Skip past the APP/Sequnce byte and the token length */ + + buffer_ptr = (unsigned char *) token->value; - buffer_ptr = (unsigned char *) token->value; - - if (*(buffer_ptr++) != 0x60) - return (GSS_S_DEFECTIVE_TOKEN); - length = *buffer_ptr++; + 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); + 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); +} - OID->length = (OM_uint32) *(buffer_ptr++); - OID->elements = (void *) buffer_ptr; - return (GSS_S_COMPLETE); +/* + * The following mechanisms do not always identify themselves + * per the GSS-API specification, when interoperating with MS + * peers. We include the OIDs here so we do not have to link + * with the mechanism. + */ +static gss_OID_desc gss_ntlm_mechanism_oid_desc = + {10, (void *)"\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"}; +static gss_OID_desc gss_spnego_mechanism_oid_desc = + {6, (void *)"\x2b\x06\x01\x05\x05\x02"}; +static gss_OID_desc gss_krb5_mechanism_oid_desc = + {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"}; + +#define NTLMSSP_SIGNATURE "NTLMSSP" + +OM_uint32 gssint_get_mech_type(OID, token) + gss_OID OID; + gss_buffer_t token; +{ + /* Check for interoperability exceptions */ + if (token->length >= sizeof(NTLMSSP_SIGNATURE) && + memcmp(token->value, NTLMSSP_SIGNATURE, + sizeof(NTLMSSP_SIGNATURE)) == 0) { + *OID = gss_ntlm_mechanism_oid_desc; + } else if (token->length != 0 && + ((char *)token->value)[0] == 0x6E) { + /* Could be a raw AP-REQ (check for APPLICATION tag) */ + *OID = gss_krb5_mechanism_oid_desc; + } else if (token->length == 0) { + *OID = gss_spnego_mechanism_oid_desc; + } else { + return gssint_get_mech_type_oid(OID, token); + } + + 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) + +#if 0 /* SUNW17PACresync */ +#include "mglueP.h" +#endif + +OM_uint32 gssint_import_internal_name (minor_status, mech_type, union_name, + internal_name) OM_uint32 *minor_status; -const gss_OID mech_type; +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 status; + gss_mechanism mech; + + mech = gssint_get_mechanism (mech_type); + if (mech) { + if (mech->gss_import_name) { + status = mech->gss_import_name ( + mech->context, /* SUNW17PACresync */ + minor_status, + union_name->external_name, + union_name->name_type, + internal_name); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } 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 gssint_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 status; + gss_mechanism mech; + gss_buffer_desc dispName; + gss_OID nameOid; + unsigned char *buf = NULL; + const unsigned char tokId[] = "\x04\x01"; + const unsigned int tokIdLen = 2; + const int mechOidLenLen = 2, mechOidTagLen = 1, nameLenLen = 4; + int mechOidDERLen = 0; + int mechOidLen = 0; + + mech = gssint_get_mechanism(mech_type); + if (!mech) + return (GSS_S_BAD_MECH); -OM_uint32 __gss_display_internal_name(minor_status, mech_type, internal_name, - external_name, name_type) -OM_uint32 *minor_status; -const gss_OID mech_type; -const gss_name_t internal_name; -gss_buffer_t external_name; -gss_OID *name_type; + if (mech->gss_export_name) { + status = mech->gss_export_name( + mech->context, /* SUNW17PACresync */ + minor_status, + internal_name, + name_buf); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + return status; + } + + /* + * 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) { + map_error(minor_status, mech); + return (status); + } + + /* determine the size of the buffer needed */ + mechOidDERLen = gssint_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; + store_16_be(mechOidLen, buf); + buf += 2; + + /* + * DER Encoding of mech OID contains OID Tag (0x06), length and + * mech OID value + */ + *buf++ = 0x06; + if (gssint_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 */ + store_32_be(dispName.length, buf); + buf += 4; + + /* 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); +} /* gssint_export_internal_name */ + +OM_uint32 gssint_display_internal_name (minor_status, mech_type, internal_name, + external_name, name_type) +OM_uint32 *minor_status; +gss_OID mech_type; +gss_name_t internal_name; +gss_buffer_t external_name; +gss_OID *name_type; { - OM_uint32 status; - gss_mechanism mech; - - mech = __gss_get_mechanism(mech_type); - if (mech) { - if (mech->gss_display_name) - status = mech->gss_display_name( - mech->context, - minor_status, - internal_name, - external_name, - name_type); - else - status = GSS_S_UNAVAILABLE; - - return (status); - } + OM_uint32 status; + gss_mechanism mech; + + mech = gssint_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); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_UNAVAILABLE; + + return (status); + } + + return (GSS_S_BAD_MECH); +} - return (GSS_S_BAD_MECH); +OM_uint32 gssint_release_internal_name (minor_status, mech_type, internal_name) +OM_uint32 *minor_status; +gss_OID mech_type; +gss_name_t *internal_name; +{ + OM_uint32 status; + gss_mechanism mech; + + mech = gssint_get_mechanism (mech_type); + if (mech) { + if (mech->gss_release_name) { + status = mech->gss_release_name ( + mech->context, + minor_status, + internal_name); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } 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 gssint_delete_internal_sec_context (minor_status, + mech_type, + internal_ctx, + output_token) +OM_uint32 *minor_status; +gss_OID mech_type; +gss_ctx_id_t *internal_ctx; +gss_buffer_t output_token; { - 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); - } + OM_uint32 status; + gss_mechanism mech; + + mech = gssint_get_mechanism (mech_type); + if (mech) { + if (mech->gss_delete_sec_context) + status = mech->gss_delete_sec_context ( + mech->context, /* SUNW17PACresync */ + minor_status, + internal_ctx, + output_token); + else + /* SUNW17PACresync - map error here? */ + status = GSS_S_UNAVAILABLE; - return (GSS_S_BAD_MECH); -} + 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 gssint_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); + 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) { + major_status = GSS_S_FAILURE; + *minor_status = ENOMEM; + map_errcode(minor_status); + 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) { + map_errcode(minor_status); + goto allocation_failure; + } + + union_name->external_name = + (gss_buffer_t) malloc(sizeof(gss_buffer_desc)); + if (!union_name->external_name) { + major_status = GSS_S_FAILURE; + *minor_status = ENOMEM; + goto allocation_failure; + } + + major_status = mech->gss_display_name( + mech->context, /* SUNW17PACresync */ + minor_status, + internal_name, + union_name->external_name, + &union_name->name_type); + if (major_status != GSS_S_COMPLETE) { + map_error(minor_status, mech); + goto allocation_failure; + } + + union_name->loopback = union_name; + *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); + 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); } - /* - * 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); + 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) gssint_release_internal_name(&tmp, &mech->mech_type, + &internal_name); + return (major_status); } /* @@ -523,22 +622,45 @@ allocation_failure: * 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; +gssint_get_mechanism_cred(union_cred, mech_type) + gss_union_cred_t union_cred; + 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]); + int i; + + if (union_cred == (gss_union_cred_t) GSS_C_NO_CREDENTIAL) + return GSS_C_NO_CREDENTIAL; + + /* + * SUNW17PACresync + * Disable this block as it causes problems for gss_add_cred + * for HTTP SSO (and also probably causes STC gss.13 to fail too). + */ +#if 0 + /* SPNEGO mechanism will again call into GSSAPI */ + if (g_OID_equal(&gss_spnego_mechanism_oid_desc, mech_type)) + return (gss_cred_id_t)union_cred; +#endif + + 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]; + + /* for SPNEGO, check the next-lower set of creds */ + if (g_OID_equal(&gss_spnego_mechanism_oid_desc, &union_cred->mechs_array[i])) { + gss_union_cred_t candidate_cred; + gss_cred_id_t sub_cred; + + candidate_cred = (gss_union_cred_t)union_cred->cred_array[i]; + sub_cred = gssint_get_mechanism_cred(candidate_cred, mech_type); + + if(sub_cred != GSS_C_NO_CREDENTIAL) + return sub_cred; } - return (GSS_C_NO_CREDENTIAL); -} + } + return GSS_C_NO_CREDENTIAL; +} /* * Routine to create and copy the gss_buffer_desc structure. @@ -546,40 +668,41 @@ __gss_get_mechanism_cred(union_cred, mech_type) */ OM_uint32 gssint_create_copy_buffer(srcBuf, destBuf, addNullChar) - const gss_buffer_t srcBuf; - gss_buffer_t *destBuf; - int addNullChar; + const gss_buffer_t srcBuf; + gss_buffer_t *destBuf; + int addNullChar; { - gss_buffer_t aBuf; - int len; + gss_buffer_t aBuf; + unsigned int len; - if (destBuf == NULL) - return (GSS_S_CALL_INACCESSIBLE_WRITE); + if (destBuf == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); - *destBuf = 0; + *destBuf = 0; - aBuf = (gss_buffer_t)malloc(sizeof (gss_buffer_desc)); - if (!aBuf) - return (GSS_S_FAILURE); + 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 (addNullChar) + len = srcBuf->length + 1; + else + len = srcBuf->length; + + if (!(aBuf->value = (void*)malloc(len))) { + free(aBuf); + return (GSS_S_FAILURE); + } - 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; - (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'; - /* optionally add a NULL character */ - if (addNullChar) - ((char *)aBuf->value)[aBuf->length] = '\0'; + return (GSS_S_COMPLETE); +} /* ****** gssint_create_copy_buffer ****** */ - return (GSS_S_COMPLETE); -} /* ****** __gss_create_copy_buffer ****** */ diff --git a/usr/src/lib/libgss/g_inq_context_oid.c b/usr/src/lib/libgss/g_inq_context_oid.c new file mode 100644 index 0000000000..c7cebe86a9 --- /dev/null +++ b/usr/src/lib/libgss/g_inq_context_oid.c @@ -0,0 +1,77 @@ +/* + * Copyright 2008 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * glue routine for gss_inquire_sec_context_by_oid + */ + +#include "mglueP.h" +#define gssint_get_mechanism __gss_get_mechanism /* SUNW17PACresync */ + +OM_uint32 +gss_inquire_sec_context_by_oid (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + OM_uint32 status; + gss_union_ctx_id_t ctx; + gss_mechanism mech; + + if (minor_status == 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 = gssint_get_mechanism (ctx->mech_type); + + if (mech != NULL) { + if (mech->gss_inquire_sec_context_by_oid != NULL) { + status = mech->gss_inquire_sec_context_by_oid(minor_status, + ctx->internal_ctx_id, + desired_object, + data_set); + if (status != GSS_S_COMPLETE) + map_error(minor_status, mech); + } else + status = GSS_S_BAD_MECH; + + return status; + } + + return GSS_S_NO_CONTEXT; +} + diff --git a/usr/src/lib/libgss/mapfile-vers b/usr/src/lib/libgss/mapfile-vers index 33fc9550c3..0552423bab 100644 --- a/usr/src/lib/libgss/mapfile-vers +++ b/usr/src/lib/libgss/mapfile-vers @@ -52,6 +52,7 @@ SUNW_1.2 { GSS_C_NT_MACHINE_UID_NAME; GSS_C_NT_STRING_UID_NAME; GSS_C_NT_USER_NAME; + GSS_C_INQ_SSPI_SESSION_KEY; gss_compare_name; gss_context_time; gss_create_empty_oid_set; @@ -87,6 +88,10 @@ SUNW_1.2 { gss_verify_mic; gss_wrap; gss_wrap_size_limit; + gss_add_buffer_set_member; + gss_create_empty_buffer_set; + gss_release_buffer_set; + gss_inquire_sec_context_by_oid; } SUNW_1.1; # Due to mistakes made early in the history of this library, there are @@ -112,6 +117,7 @@ SUNWprivate_1.1 { gsscred_set_options; gss_get_group_info; __gss_get_kmodName; + __gss_get_mechanism; __gss_get_mechanisms; __gss_get_mech_info; __gss_get_mech_type; |
