Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / rpc / sec_gss / rpcsec_gss_utils.c
blob93ecae3da3c01c4622f6aa360ac9bcaf493df68b
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 1996-1997,2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <sys/systm.h>
30 #include <sys/errno.h>
31 #include <sys/cmn_err.h>
32 #include <gssapi/gssapi.h>
33 #include <rpc/rpc.h>
34 #include <rpc/rpcsec_defs.h>
36 #ifdef RPCGSS_DEBUG
38 * Kernel rpcsec_gss module debugging aid. The global variable "rpcgss_log"
39 * is a bit mask which allows various types of debugging messages to be printed
40 * out.
42 * rpcgss_log & 1 will cause actual failures to be printed.
43 * rpcgss_log & 2 will cause informational messages to be
44 * printed on the client side of rpcsec_gss.
45 * rpcgss_log & 4 will cause informational messages to be
46 * printed on the server side of rpcsec_gss.
47 * rpcgss_log & 8 will cause informational messages to be
48 * printed on both client and server side of rpcsec_gss.
51 uint_t rpcgss_log = 0;
53 #endif /* RPCGSS_DEBUG */
56 * Internal utility routines.
60 * Duplicate a gss_OID value.
62 void
63 __rpc_gss_dup_oid(gss_OID oid, gss_OID *ret)
65 gss_OID tmp;
67 if (oid == GSS_C_NULL_OID || oid->length == 0) {
68 *ret = NULL;
69 return;
72 tmp = (gss_OID) kmem_alloc(sizeof (gss_OID_desc), KM_SLEEP);
73 if (tmp) {
74 tmp->elements = kmem_alloc((oid->length), KM_SLEEP);
75 bcopy((char *)oid->elements, (char *)tmp->elements, oid->length);
76 tmp->length = oid->length;
77 *ret = tmp;
78 } else {
79 *ret = NULL;
84 * Check if 2 gss_OID are the same.
86 bool_t
87 __rpc_gss_oids_equal(oid1, oid2)
88 gss_OID oid1, oid2;
90 if ((oid1->length == 0) && (oid2->length == 0))
91 return (TRUE);
93 if (oid1->length != oid2->length)
94 return (FALSE);
96 return (bcmp(oid1->elements, oid2->elements, oid1->length) == 0);
99 void
100 __rpc_gss_convert_name(principal, name, name_type)
101 rpc_gss_principal_t principal;
102 gss_buffer_desc *name;
103 gss_OID *name_type;
105 char *cp;
107 cp = principal->name;
108 if (*(int *)cp == 0)
109 *name_type = GSS_C_NULL_OID;
110 else {
111 (*name_type)->length = *(int *)cp;
112 (*name_type)->elements = (void *)(cp + sizeof (int));
114 cp += RNDUP(*(int *)cp) + sizeof (int);
115 if ((name->length = *(int *)cp) == 0)
116 name->value = NULL;
117 else
118 name->value = cp + sizeof (int);
122 * Make a client principal name from a flat exported gss name.
124 bool_t
125 __rpc_gss_make_principal(principal, name)
126 rpc_gss_principal_t *principal;
127 gss_buffer_desc *name;
129 int plen;
130 char *s;
132 RPCGSS_LOG(8, "name-length = %lu\n", name->length);
133 RPCGSS_LOG(8, "name-value = 0x%p\n", (void *)name->value);
135 plen = RNDUP(name->length) + sizeof (int);
136 (*principal) = (rpc_gss_principal_t)kmem_alloc(plen, KM_SLEEP);
137 if ((*principal) == NULL)
138 return (FALSE);
139 bzero((caddr_t)(*principal), plen);
140 (*principal)->len = RNDUP(name->length);
141 s = (*principal)->name;
142 bcopy(name->value, s, name->length);
143 return (TRUE);
148 * Make a copy of a principal name.
150 rpc_gss_principal_t
151 __rpc_gss_dup_principal(principal)
152 rpc_gss_principal_t principal;
154 rpc_gss_principal_t pdup;
155 int len;
157 if (principal == NULL)
158 return (NULL);
159 len = principal->len + sizeof (int);
160 if ((pdup = (rpc_gss_principal_t)mem_alloc(len)) == NULL)
161 return (NULL);
162 pdup->len = len;
163 bcopy(principal->name, pdup->name, len);
164 return (pdup);
168 * Returns highest and lowest versions of RPCSEC_GSS flavor supported.
170 bool_t
171 rpc_gss_get_versions(vers_hi, vers_lo)
172 uint_t *vers_hi;
173 uint_t *vers_lo;
175 *vers_hi = RPCSEC_GSS_VERSION;
176 *vers_lo = RPCSEC_GSS_VERSION;
177 return (TRUE);
180 void
181 rpc_gss_display_status(major, minor, mech_type,
182 uid, gss_function_name)
183 OM_uint32 major, minor;
184 gss_OID mech_type;
185 uid_t uid;
186 char *gss_function_name;
189 int message_context;
190 int major_stat;
191 uint_t minor_stat;
192 gss_buffer_desc status_string;
195 * Before we return let us see
196 * whether we can log more meaningful error
197 * string using kgss_display_status
198 * If we can not just log the gssstat in hex
199 * and return.
201 message_context = 0;
204 * First get the status string out of gss_major_code
207 do {
208 major_stat = kgss_display_status(&minor_stat, major,
209 GSS_C_GSS_CODE, mech_type,
210 &message_context, &status_string, uid);
212 * If we failed just log the original error codes
214 if (major_stat != GSS_S_COMPLETE &&
215 major != GSS_S_CONTINUE_NEEDED) {
217 RPCGSS_LOG1(1, "%s GSS major error 0x%x\n",
218 gss_function_name, major);
219 RPCGSS_LOG1(1, "%s GSS minor error 0x%x\n",
220 gss_function_name, minor);
222 return;
223 } else {
224 RPCGSS_LOG1(1, "%s GSS Error %s\n",
225 (char *)gss_function_name,
226 (char *)status_string.value);
227 (void) gss_release_buffer(&minor_stat, &status_string);
229 } while (message_context != 0);
231 * Now get the status string out of gss_minor_code
232 * This is mechanism specific error which is most
233 * useful
235 message_context = 0;
236 do {
237 major_stat = kgss_display_status(&minor_stat, minor,
238 GSS_C_MECH_CODE, mech_type,
239 &message_context, &status_string, uid);
240 if (major_stat != GSS_S_COMPLETE &&
241 major_stat != GSS_S_CONTINUE_NEEDED) {
242 RPCGSS_LOG1(1, "%s GSS minor error 0x%x\n",
243 gss_function_name, minor);
244 return;
245 } else {
246 RPCGSS_LOG1(1,
247 "%s GSS Minor Error %s\n",
248 (char *)gss_function_name, (char *)status_string.value);
249 (void) gss_release_buffer(&minor_stat,
250 &status_string);
252 } while (message_context != 0);