xref: /freebsd/crypto/krb5/src/lib/gssapi/mechglue/g_compare_name.c (revision f1c4c3daccbaf3820f0e2224de53df12fc952fcc)
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
val_comp_name_args(OM_uint32 * minor_status,gss_name_t name1,gss_name_t name2,int * name_equal)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
gss_compare_name(OM_uint32 * minor_status,gss_name_t name1,gss_name_t name2,int * name_equal)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