1 /* #pragma ident "@(#)g_compare_name.c 1.16 04/02/23 SMI" */ 2 3 /* 4 * Copyright 1996 by Sun Microsystems, Inc. 5 * 6 * Permission to use, copy, modify, distribute, and sell this software 7 * and its documentation for any purpose is hereby granted without fee, 8 * provided that the above copyright notice appears in all copies and 9 * that both that copyright notice and this permission notice appear in 10 * supporting documentation, and that the name of Sun Microsystems not be used 11 * in advertising or publicity pertaining to distribution of the software 12 * without specific, written prior permission. Sun Microsystems makes no 13 * representations about the suitability of this software for any 14 * purpose. It is provided "as is" without express or implied warranty. 15 * 16 * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 18 * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 20 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 21 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 22 * PERFORMANCE OF THIS SOFTWARE. 23 */ 24 25 /* 26 * glue routine for gss_compare_name 27 * 28 */ 29 30 #include "mglueP.h" 31 #ifdef HAVE_STDLIB_H 32 #include <stdlib.h> 33 #endif 34 #include <string.h> 35 36 static OM_uint32 37 val_comp_name_args( 38 OM_uint32 *minor_status, 39 gss_name_t name1, 40 gss_name_t name2, 41 int *name_equal) 42 { 43 44 /* Initialize outputs. */ 45 46 if (minor_status != NULL) 47 *minor_status = 0; 48 49 /* Validate arguments. */ 50 51 if (name1 == GSS_C_NO_NAME || name2 == GSS_C_NO_NAME) 52 return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME); 53 54 if (name_equal == NULL) 55 return (GSS_S_CALL_INACCESSIBLE_WRITE); 56 57 return (GSS_S_COMPLETE); 58 } 59 60 61 OM_uint32 KRB5_CALLCONV 62 gss_compare_name(OM_uint32 * minor_status, gss_name_t name1, gss_name_t name2, 63 int * name_equal) 64 { 65 OM_uint32 major_status, temp_minor; 66 gss_union_name_t union_name1, union_name2; 67 gss_mechanism mech = NULL; 68 gss_name_t internal_name; 69 70 major_status = val_comp_name_args(minor_status, 71 name1, name2, name_equal); 72 if (major_status != GSS_S_COMPLETE) 73 return (major_status); 74 75 union_name1 = (gss_union_name_t) name1; 76 union_name2 = (gss_union_name_t) name2; 77 /* 78 * Try our hardest to make union_name1 be the mechanism-specific 79 * name. (Of course we can't if both names aren't 80 * mechanism-specific.) 81 */ 82 if (union_name1->mech_type == 0) { 83 union_name1 = (gss_union_name_t) name2; 84 union_name2 = (gss_union_name_t) name1; 85 } 86 /* 87 * If union_name1 is mechanism specific, then fetch its mechanism 88 * information. 89 */ 90 if (union_name1->mech_type) { 91 mech = gssint_get_mechanism (union_name1->mech_type); 92 if (!mech) 93 return (GSS_S_BAD_MECH); 94 if (!mech->gss_compare_name) 95 return (GSS_S_UNAVAILABLE); 96 } 97 98 *name_equal = 0; /* Default to *not* equal.... */ 99 100 /* 101 * First case... both names are mechanism-specific 102 */ 103 if (union_name1->mech_type && union_name2->mech_type) { 104 if (!g_OID_equal(union_name1->mech_type, union_name2->mech_type)) 105 return (GSS_S_COMPLETE); 106 if ((union_name1->mech_name == 0) || (union_name2->mech_name == 0)) 107 /* should never happen */ 108 return (GSS_S_BAD_NAME); 109 if (!mech) 110 return (GSS_S_BAD_MECH); 111 if (!mech->gss_compare_name) 112 return (GSS_S_UNAVAILABLE); 113 major_status = mech->gss_compare_name(minor_status, 114 union_name1->mech_name, 115 union_name2->mech_name, 116 name_equal); 117 if (major_status != GSS_S_COMPLETE) 118 map_error(minor_status, mech); 119 return major_status; 120 } 121 122 /* 123 * Second case... both names are NOT mechanism specific. 124 * 125 * All we do here is make sure the two name_types are equal and then 126 * that the external_names are equal. Note the we do not take care 127 * of the case where two different external names map to the same 128 * internal name. We cannot determine this, since we as yet do not 129 * know what mechanism to use for calling the underlying 130 * gss_import_name(). 131 */ 132 if (!union_name1->mech_type && !union_name2->mech_type) { 133 /* 134 * Second case, first sub-case... one name has null 135 * name_type, the other doesn't. 136 * 137 * Not knowing a mech_type we can't import the name with 138 * null name_type so we can't compare. 139 */ 140 if ((union_name1->name_type == GSS_C_NULL_OID && 141 union_name2->name_type != GSS_C_NULL_OID) || 142 (union_name1->name_type != GSS_C_NULL_OID && 143 union_name2->name_type == GSS_C_NULL_OID)) 144 return (GSS_S_COMPLETE); 145 /* 146 * Second case, second sub-case... both names have 147 * name_types, but they are different. 148 */ 149 if ((union_name1->name_type != GSS_C_NULL_OID && 150 union_name2->name_type != GSS_C_NULL_OID) && 151 !g_OID_equal(union_name1->name_type, 152 union_name2->name_type)) 153 return (GSS_S_COMPLETE); 154 /* 155 * Second case, third sub-case... both names have equal 156 * name_types (and both have no mech_types) so we just 157 * compare the external_names. 158 */ 159 if ((union_name1->external_name->length != 160 union_name2->external_name->length) || 161 (memcmp(union_name1->external_name->value, 162 union_name2->external_name->value, 163 union_name1->external_name->length) != 0)) 164 return (GSS_S_COMPLETE); 165 *name_equal = 1; 166 return (GSS_S_COMPLETE); 167 } 168 169 /* 170 * Final case... one name is mechanism specific, the other isn't. 171 * 172 * We attempt to convert the general name to the mechanism type of 173 * the mechanism-specific name, and then do the compare. If we 174 * can't import the general name, then we return that the name is 175 * _NOT_ equal. 176 */ 177 if (union_name2->mech_type) { 178 /* We make union_name1 the mechanism specific name. */ 179 union_name1 = (gss_union_name_t) name2; 180 union_name2 = (gss_union_name_t) name1; 181 } 182 major_status = gssint_import_internal_name(minor_status, 183 union_name1->mech_type, 184 union_name2, 185 &internal_name); 186 if (major_status != GSS_S_COMPLETE) 187 return (GSS_S_COMPLETE); /* return complete, but not equal */ 188 189 if (!mech) 190 return (GSS_S_BAD_MECH); 191 if (!mech->gss_compare_name) 192 return (GSS_S_UNAVAILABLE); 193 major_status = mech->gss_compare_name(minor_status, 194 union_name1->mech_name, 195 internal_name, name_equal); 196 if (major_status != GSS_S_COMPLETE) 197 map_error(minor_status, mech); 198 gssint_release_internal_name(&temp_minor, union_name1->mech_type, 199 &internal_name); 200 return (major_status); 201 202 } 203