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
val_comp_name_args(OM_uint32 * minor_status,gss_name_t name1,gss_name_t name2,int * name_equal)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
gss_compare_name(minor_status,name1,name2,name_equal)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