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