Home | History | Annotate | Download | only in libgss
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*
     27  *  glue routine for gss_compare_name
     28  *
     29  */
     30 
     31 #include <mechglueP.h>
     32 #ifdef HAVE_STDLIB_H
     33 #include <stdlib.h>
     34 #endif
     35 #include <string.h>
     36 
     37 static OM_uint32
     38 val_comp_name_args(
     39 	OM_uint32 *minor_status,
     40 	gss_name_t name1,
     41 	gss_name_t name2,
     42 	int *name_equal)
     43 {
     44 
     45 	/* Initialize outputs. */
     46 
     47 	if (minor_status != NULL)
     48 		*minor_status = 0;
     49 
     50 	/* Validate arguments. */
     51 
     52 	if (name1 == GSS_C_NO_NAME || name2 == GSS_C_NO_NAME)
     53 		return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
     54 
     55 	if (name_equal == NULL)
     56 		return (GSS_S_CALL_INACCESSIBLE_WRITE);
     57 
     58 	return (GSS_S_COMPLETE);
     59 }
     60 
     61 OM_uint32
     62 gss_compare_name(minor_status,
     63 			name1,
     64 			name2,
     65 			name_equal)
     66 
     67 OM_uint32 *minor_status;
     68 const gss_name_t name1;
     69 const gss_name_t name2;
     70 int *name_equal;
     71 
     72 {
     73 	OM_uint32		major_status, temp_minor;
     74 	gss_union_name_t	union_name1, union_name2;
     75 	gss_mechanism		mech;
     76 	gss_name_t		internal_name;
     77 
     78 	major_status = val_comp_name_args(minor_status,
     79 					name1, name2, name_equal);
     80 	if (major_status != GSS_S_COMPLETE)
     81 		return (major_status);
     82 
     83 	union_name1 = (gss_union_name_t)name1;
     84 	union_name2 = (gss_union_name_t)name2;
     85 	/*
     86 	 * Try our hardest to make union_name1 be the mechanism-specific
     87 	 * name.  (Of course we can't if both names aren't
     88 	 * mechanism-specific.)
     89 	 */
     90 	if (union_name1->mech_type == 0) {
     91 		union_name1 = (gss_union_name_t)name2;
     92 		union_name2 = (gss_union_name_t)name1;
     93 	}
     94 	/*
     95 	 * If union_name1 is mechanism specific, then fetch its mechanism
     96 	 * information.
     97 	 */
     98 	if (union_name1->mech_type) {
     99 		mech = __gss_get_mechanism(union_name1->mech_type);
    100 		if (!mech)
    101 			return (GSS_S_BAD_MECH);
    102 		if (!mech->gss_compare_name)
    103 			return (GSS_S_UNAVAILABLE);
    104 	}
    105 
    106 	*name_equal = 0;	/* Default to *not* equal.... */
    107 
    108 	/*
    109 	 * First case... both names are mechanism-specific
    110 	 */
    111 	if (union_name1->mech_type && union_name2->mech_type) {
    112 		if (!g_OID_equal(union_name1->mech_type,
    113 					union_name2->mech_type))
    114 			return (GSS_S_COMPLETE);
    115 		if ((union_name1->mech_name == 0) ||
    116 			(union_name2->mech_name == 0))
    117 			/* should never happen */
    118 			return (GSS_S_BAD_NAME);
    119 		return (mech->gss_compare_name(mech->context, minor_status,
    120 							union_name1->mech_name,
    121 							union_name2->mech_name,
    122 							name_equal));
    123 	}
    124 
    125 	/*
    126 	 * Second case... both names are NOT mechanism specific.
    127 	 *
    128 	 * All we do here is make sure the two name_types are equal and then
    129 	 * that the external_names are equal. Note the we do not take care
    130 	 * of the case where two different external names map to the same
    131 	 * internal name. We cannot determine this, since we as yet do not
    132 	 * know what mechanism to use for calling the underlying
    133 	 * gss_import_name().
    134 	 */
    135 	if (!union_name1->mech_type && !union_name2->mech_type) {
    136 		/*
    137 		 * Second case, first sub-case... one name has null
    138 		 * name_type, the other doesn't.
    139 		 *
    140 		 * Not knowing a mech_type we can't import the name with
    141 		 * null name_type so we can't compare.
    142 		 */
    143 		if ((union_name1->name_type == GSS_C_NULL_OID &&
    144 		    union_name2->name_type != GSS_C_NULL_OID) ||
    145 		    (union_name1->name_type != GSS_C_NULL_OID &&
    146 		    union_name2->name_type == GSS_C_NULL_OID))
    147 			return (GSS_S_COMPLETE);
    148 		/*
    149 		 * Second case, second sub-case... both names have
    150 		 * name_types, but they are different.
    151 		 */
    152 		if ((union_name1->name_type != GSS_C_NULL_OID &&
    153 		    union_name2->name_type != GSS_C_NULL_OID) &&
    154 		    !g_OID_equal(union_name1->name_type,
    155 					union_name2->name_type))
    156 			return (GSS_S_COMPLETE);
    157 		/*
    158 		 * Second case, third sub-case... both names have equal
    159 		 * name_types (and both have no mech_types) so we just
    160 		 * compare the external_names.
    161 		 */
    162 		if ((union_name1->external_name->length !=
    163 			union_name2->external_name->length) ||
    164 			(memcmp(union_name1->external_name->value,
    165 				union_name2->external_name->value,
    166 				union_name1->external_name->length) != 0))
    167 			return (GSS_S_COMPLETE);
    168 		*name_equal = 1;
    169 		return (GSS_S_COMPLETE);
    170 	}
    171 
    172 	/*
    173 	 * Final case... one name is mechanism specific, the other isn't.
    174 	 *
    175 	 * We attempt to convert the general name to the mechanism type of
    176 	 * the mechanism-specific name, and then do the compare.  If we
    177 	 * can't import the general name, then we return that the name is
    178 	 * _NOT_ equal.
    179 	 */
    180 	if (union_name2->mech_type) {
    181 		/* We make union_name1 the mechanism specific name. */
    182 		union_name1 = (gss_union_name_t)name2;
    183 		union_name2 = (gss_union_name_t)name1;
    184 	}
    185 	major_status = __gss_import_internal_name(minor_status,
    186 							union_name1->mech_type,
    187 							union_name2,
    188 							&internal_name);
    189 	if (major_status != GSS_S_COMPLETE)
    190 		return (GSS_S_COMPLETE); /* return complete, but not equal */
    191 
    192 	major_status = mech->gss_compare_name(mech->context, minor_status,
    193 							union_name1->mech_name,
    194 							internal_name,
    195 							name_equal);
    196 	(void) __gss_release_internal_name(&temp_minor, union_name1->mech_type,
    197 					&internal_name);
    198 	return (major_status);
    199 }
    200