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 (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /* 26 * glue routine for gss_compare_name 27 * 28 */ 29 30 #include <mechglueP.h> 31 #include "gssapiP_generic.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 = NULL; 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 if (!mech) 120 return (GSS_S_BAD_MECH); 121 if (!mech->gss_compare_name) 122 return (GSS_S_UNAVAILABLE); 123 major_status = mech->gss_compare_name(mech->context, 124 minor_status, 125 union_name1->mech_name, 126 union_name2->mech_name, 127 name_equal); 128 if (major_status != GSS_S_COMPLETE) 129 map_error(minor_status, mech); 130 return major_status; 131 } 132 133 /* 134 * Second case... both names are NOT mechanism specific. 135 * 136 * All we do here is make sure the two name_types are equal and then 137 * that the external_names are equal. Note the we do not take care 138 * of the case where two different external names map to the same 139 * internal name. We cannot determine this, since we as yet do not 140 * know what mechanism to use for calling the underlying 141 * gss_import_name(). 142 */ 143 if (!union_name1->mech_type && !union_name2->mech_type) { 144 /* 145 * Second case, first sub-case... one name has null 146 * name_type, the other doesn't. 147 * 148 * Not knowing a mech_type we can't import the name with 149 * null name_type so we can't compare. 150 */ 151 if ((union_name1->name_type == GSS_C_NULL_OID && 152 union_name2->name_type != GSS_C_NULL_OID) || 153 (union_name1->name_type != GSS_C_NULL_OID && 154 union_name2->name_type == GSS_C_NULL_OID)) 155 return (GSS_S_COMPLETE); 156 /* 157 * Second case, second sub-case... both names have 158 * name_types, but they are different. 159 */ 160 if ((union_name1->name_type != GSS_C_NULL_OID && 161 union_name2->name_type != GSS_C_NULL_OID) && 162 !g_OID_equal(union_name1->name_type, 163 union_name2->name_type)) 164 return (GSS_S_COMPLETE); 165 /* 166 * Second case, third sub-case... both names have equal 167 * name_types (and both have no mech_types) so we just 168 * compare the external_names. 169 */ 170 if ((union_name1->external_name->length != 171 union_name2->external_name->length) || 172 (memcmp(union_name1->external_name->value, 173 union_name2->external_name->value, 174 union_name1->external_name->length) != 0)) 175 return (GSS_S_COMPLETE); 176 *name_equal = 1; 177 return (GSS_S_COMPLETE); 178 } 179 180 /* 181 * Final case... one name is mechanism specific, the other isn't. 182 * 183 * We attempt to convert the general name to the mechanism type of 184 * the mechanism-specific name, and then do the compare. If we 185 * can't import the general name, then we return that the name is 186 * _NOT_ equal. 187 */ 188 if (union_name2->mech_type) { 189 /* We make union_name1 the mechanism specific name. */ 190 union_name1 = (gss_union_name_t)name2; 191 union_name2 = (gss_union_name_t)name1; 192 } 193 major_status = __gss_import_internal_name(minor_status, 194 union_name1->mech_type, 195 union_name2, 196 &internal_name); 197 if (major_status != GSS_S_COMPLETE) 198 return (GSS_S_COMPLETE); /* return complete, but not equal */ 199 200 if (!mech) 201 return (GSS_S_BAD_MECH); 202 if (!mech->gss_compare_name) 203 return (GSS_S_UNAVAILABLE); 204 major_status = mech->gss_compare_name(mech->context, minor_status, 205 union_name1->mech_name, 206 internal_name, 207 name_equal); 208 if (major_status != GSS_S_COMPLETE) 209 map_error(minor_status, mech); 210 (void) __gss_release_internal_name(&temp_minor, union_name1->mech_type, 211 &internal_name); 212 return (major_status); 213 } 214