1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate * CDDL HEADER START
3*0Sstevel@tonic-gate *
4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*0Sstevel@tonic-gate * with the License.
8*0Sstevel@tonic-gate *
9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate * and limitations under the License.
13*0Sstevel@tonic-gate *
14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate *
20*0Sstevel@tonic-gate * CDDL HEADER END
21*0Sstevel@tonic-gate */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate * name.c
24*0Sstevel@tonic-gate *
25*0Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
26*0Sstevel@tonic-gate * Use is subject to license terms.
27*0Sstevel@tonic-gate *
28*0Sstevel@tonic-gate */
29*0Sstevel@tonic-gate
30*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
31*0Sstevel@tonic-gate
32*0Sstevel@tonic-gate #include "dh_gssapi.h"
33*0Sstevel@tonic-gate #include <pwd.h>
34*0Sstevel@tonic-gate #include <string.h>
35*0Sstevel@tonic-gate #include <stdlib.h>
36*0Sstevel@tonic-gate #include <sys/types.h>
37*0Sstevel@tonic-gate #include <sys/param.h>
38*0Sstevel@tonic-gate #include <sys/note.h>
39*0Sstevel@tonic-gate #include <thread.h>
40*0Sstevel@tonic-gate
41*0Sstevel@tonic-gate extern int
42*0Sstevel@tonic-gate get_der_length(unsigned char **, unsigned int, unsigned int *);
43*0Sstevel@tonic-gate
44*0Sstevel@tonic-gate extern unsigned int
45*0Sstevel@tonic-gate der_length_size(unsigned int);
46*0Sstevel@tonic-gate
47*0Sstevel@tonic-gate extern int
48*0Sstevel@tonic-gate put_der_length(unsigned int, unsigned char **, unsigned int);
49*0Sstevel@tonic-gate
50*0Sstevel@tonic-gate /* Diffie-Hellman ONC RPC netname name type */
51*0Sstevel@tonic-gate static gss_OID_desc __DH_GSS_C_NT_NETNAME_desc =
52*0Sstevel@tonic-gate { 9, "\053\006\004\001\052\002\032\001\001" };
53*0Sstevel@tonic-gate
54*0Sstevel@tonic-gate const gss_OID_desc * const __DH_GSS_C_NT_NETNAME = &__DH_GSS_C_NT_NETNAME_desc;
55*0Sstevel@tonic-gate
56*0Sstevel@tonic-gate #define OID_MAX_NAME_ENTRIES 32
57*0Sstevel@tonic-gate
58*0Sstevel@tonic-gate /*
59*0Sstevel@tonic-gate * __dh_gss_compare_name: Diffie-Hellman machanism support for
60*0Sstevel@tonic-gate * gss_compare_name. Given two gss_name_ts that are presumed to
61*0Sstevel@tonic-gate * be rpc netnames set the *equal parameter to true if they are
62*0Sstevel@tonic-gate * the same, else set it to false.
63*0Sstevel@tonic-gate */
64*0Sstevel@tonic-gate
65*0Sstevel@tonic-gate OM_uint32
__dh_gss_compare_name(void * ctx,OM_uint32 * minor,gss_name_t name1,gss_name_t name2,int * equal)66*0Sstevel@tonic-gate __dh_gss_compare_name(void *ctx, /* Per mechanism context (not used) */
67*0Sstevel@tonic-gate OM_uint32 *minor, /* Mechanism status */
68*0Sstevel@tonic-gate gss_name_t name1, /* First name to compare */
69*0Sstevel@tonic-gate gss_name_t name2, /* Second name to compare */
70*0Sstevel@tonic-gate int *equal /* The result */)
71*0Sstevel@tonic-gate {
72*0Sstevel@tonic-gate _NOTE(ARGUNUSED(ctx))
73*0Sstevel@tonic-gate
74*0Sstevel@tonic-gate if (minor == 0 || equal == 0)
75*0Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE);
76*0Sstevel@tonic-gate
77*0Sstevel@tonic-gate *minor = DH_SUCCESS;
78*0Sstevel@tonic-gate
79*0Sstevel@tonic-gate if (name1 == 0 || name2 == 0) {
80*0Sstevel@tonic-gate *minor = DH_BADARG_FAILURE;
81*0Sstevel@tonic-gate return (GSS_S_BAD_NAME | GSS_S_CALL_INACCESSIBLE_READ);
82*0Sstevel@tonic-gate }
83*0Sstevel@tonic-gate
84*0Sstevel@tonic-gate *equal = (strcmp((char *)name1, (char *)name2) == 0);
85*0Sstevel@tonic-gate
86*0Sstevel@tonic-gate return (GSS_S_COMPLETE);
87*0Sstevel@tonic-gate }
88*0Sstevel@tonic-gate
89*0Sstevel@tonic-gate /*
90*0Sstevel@tonic-gate * __dh_gss_display_name: Supports gss_display_name for Diffie-Hellman
91*0Sstevel@tonic-gate * mechanism. This takes a gss internal name and converts it to
92*0Sstevel@tonic-gate * a counted string suitable for display.
93*0Sstevel@tonic-gate */
94*0Sstevel@tonic-gate OM_uint32
__dh_gss_display_name(void * ctx,OM_uint32 * minor,gss_name_t name,gss_buffer_t output,gss_OID * name_type)95*0Sstevel@tonic-gate __dh_gss_display_name(void * ctx, /* Per mechanism context (not used) */
96*0Sstevel@tonic-gate OM_uint32* minor, /* Mechanism status */
97*0Sstevel@tonic-gate gss_name_t name, /* Diffie-Hellman internal name */
98*0Sstevel@tonic-gate gss_buffer_t output, /* Were the printable name goes */
99*0Sstevel@tonic-gate gss_OID *name_type /* Name type of the internal name */)
100*0Sstevel@tonic-gate {
101*0Sstevel@tonic-gate _NOTE(ARGUNUSED(ctx))
102*0Sstevel@tonic-gate
103*0Sstevel@tonic-gate if (minor == 0 || output == 0)
104*0Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE);
105*0Sstevel@tonic-gate
106*0Sstevel@tonic-gate if (name == 0)
107*0Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
108*0Sstevel@tonic-gate
109*0Sstevel@tonic-gate *minor = DH_SUCCESS;
110*0Sstevel@tonic-gate
111*0Sstevel@tonic-gate output->length = 0;
112*0Sstevel@tonic-gate output->value = (void *)strdup((char *)name);
113*0Sstevel@tonic-gate if (output->value == NULL) {
114*0Sstevel@tonic-gate *minor = DH_NOMEM_FAILURE;
115*0Sstevel@tonic-gate return (GSS_S_FAILURE);
116*0Sstevel@tonic-gate }
117*0Sstevel@tonic-gate output->length = strlen((char *)name) + 1;
118*0Sstevel@tonic-gate
119*0Sstevel@tonic-gate /*
120*0Sstevel@tonic-gate * Note: we no longer copy the name type OID. The current draft of
121*0Sstevel@tonic-gate * the standard specifies:
122*0Sstevel@tonic-gate *
123*0Sstevel@tonic-gate * "The returned gss_OID will be a pointer into static stoarge
124*0Sstevel@tonic-gate * and should be treated as read-only by the caller (in particular,
125*0Sstevel@tonic-gate * it does not need to be freed)."
126*0Sstevel@tonic-gate *
127*0Sstevel@tonic-gate * if (name_type) {
128*0Sstevel@tonic-gate * if ((*minor = __OID_copy(name_type, __DH_GSS_C_NT_NETNAME))
129*0Sstevel@tonic-gate * != DH_SUCCESS) {
130*0Sstevel@tonic-gate * free(output->value);
131*0Sstevel@tonic-gate * output->value = NULL;
132*0Sstevel@tonic-gate * return (GSS_S_FAILURE);
133*0Sstevel@tonic-gate * }
134*0Sstevel@tonic-gate * }
135*0Sstevel@tonic-gate */
136*0Sstevel@tonic-gate
137*0Sstevel@tonic-gate if (name_type)
138*0Sstevel@tonic-gate *name_type = (gss_OID) __DH_GSS_C_NT_NETNAME;
139*0Sstevel@tonic-gate
140*0Sstevel@tonic-gate return (GSS_S_COMPLETE);
141*0Sstevel@tonic-gate }
142*0Sstevel@tonic-gate
143*0Sstevel@tonic-gate /*
144*0Sstevel@tonic-gate * Routine that takes a netname as a character string and assigns it
145*0Sstevel@tonic-gate * to a an gss_name_t pointed to by output.
146*0Sstevel@tonic-gate */
147*0Sstevel@tonic-gate static OM_uint32
do_netname_nametype(OM_uint32 * minor,char * input,gss_name_t * output)148*0Sstevel@tonic-gate do_netname_nametype(OM_uint32 *minor, char *input, gss_name_t *output)
149*0Sstevel@tonic-gate {
150*0Sstevel@tonic-gate if (__dh_validate_principal(input) != DH_SUCCESS)
151*0Sstevel@tonic-gate return (GSS_S_BAD_NAME);
152*0Sstevel@tonic-gate
153*0Sstevel@tonic-gate *minor = DH_SUCCESS;
154*0Sstevel@tonic-gate *output = (gss_name_t)strdup((char *)input);
155*0Sstevel@tonic-gate
156*0Sstevel@tonic-gate if (*output == NULL) {
157*0Sstevel@tonic-gate *minor = DH_NOMEM_FAILURE;
158*0Sstevel@tonic-gate return (GSS_S_FAILURE);
159*0Sstevel@tonic-gate }
160*0Sstevel@tonic-gate
161*0Sstevel@tonic-gate return (GSS_S_COMPLETE);
162*0Sstevel@tonic-gate }
163*0Sstevel@tonic-gate
164*0Sstevel@tonic-gate /*
165*0Sstevel@tonic-gate * do_uid_nametype converts a uid to a gss_name_t pointed to by output
166*0Sstevel@tonic-gate */
167*0Sstevel@tonic-gate static OM_uint32
do_uid_nametype(OM_uint32 * minor,uid_t uid,gss_name_t * output)168*0Sstevel@tonic-gate do_uid_nametype(OM_uint32 *minor, uid_t uid, gss_name_t *output)
169*0Sstevel@tonic-gate {
170*0Sstevel@tonic-gate char netname[MAXNETNAMELEN+1];
171*0Sstevel@tonic-gate
172*0Sstevel@tonic-gate if (!user2netname(netname, uid, NULL)) {
173*0Sstevel@tonic-gate *minor = DH_NETNAME_FAILURE;
174*0Sstevel@tonic-gate return (GSS_S_FAILURE);
175*0Sstevel@tonic-gate }
176*0Sstevel@tonic-gate return (do_netname_nametype(minor, netname, output));
177*0Sstevel@tonic-gate }
178*0Sstevel@tonic-gate
179*0Sstevel@tonic-gate /*
180*0Sstevel@tonic-gate * do_username_nametype converts a username to a gss_name_t pointed to by
181*0Sstevel@tonic-gate * output.
182*0Sstevel@tonic-gate *
183*0Sstevel@tonic-gate * A username will be represented by the following:
184*0Sstevel@tonic-gate * name[/node][@security-domain]
185*0Sstevel@tonic-gate *
186*0Sstevel@tonic-gate * Then optional security-domain will represent secure rpc domain if
187*0Sstevel@tonic-gate * present. If not present the local domain will be used. name is the
188*0Sstevel@tonic-gate * user name as found in the unix password file. If name is root and
189*0Sstevel@tonic-gate * node is present, then node will represent the host. If the host is
190*0Sstevel@tonic-gate * a qualified name we assume that it is a DNS name and will only return
191*0Sstevel@tonic-gate * the first commponnet since we want host name that are relative to
192*0Sstevel@tonic-gate * the security domain (secure rpc domain).
193*0Sstevel@tonic-gate */
194*0Sstevel@tonic-gate
195*0Sstevel@tonic-gate static OM_uint32
do_username_nametype(OM_uint32 * minor,char * uname,gss_name_t * output)196*0Sstevel@tonic-gate do_username_nametype(OM_uint32 *minor, char *uname, gss_name_t *output)
197*0Sstevel@tonic-gate {
198*0Sstevel@tonic-gate char netname[MAXNETNAMELEN+1];
199*0Sstevel@tonic-gate char *user, *node, *domain;
200*0Sstevel@tonic-gate struct passwd pwd;
201*0Sstevel@tonic-gate char buff[1024];
202*0Sstevel@tonic-gate
203*0Sstevel@tonic-gate /* Set outputs to sane values */
204*0Sstevel@tonic-gate
205*0Sstevel@tonic-gate *output = 0;
206*0Sstevel@tonic-gate *minor = DH_SUCCESS;
207*0Sstevel@tonic-gate
208*0Sstevel@tonic-gate /* See if we have a name */
209*0Sstevel@tonic-gate if (uname == 0) {
210*0Sstevel@tonic-gate *minor = DH_NO_SUCH_USER;
211*0Sstevel@tonic-gate return (GSS_S_FAILURE);
212*0Sstevel@tonic-gate }
213*0Sstevel@tonic-gate
214*0Sstevel@tonic-gate /* copy the name so that we can do surgery on it */
215*0Sstevel@tonic-gate user = strdup(uname);
216*0Sstevel@tonic-gate if (user == 0) {
217*0Sstevel@tonic-gate *minor = DH_NOMEM_FAILURE;
218*0Sstevel@tonic-gate return (GSS_S_FAILURE);
219*0Sstevel@tonic-gate }
220*0Sstevel@tonic-gate
221*0Sstevel@tonic-gate
222*0Sstevel@tonic-gate /* Look for optional node part */
223*0Sstevel@tonic-gate node = strchr(user, '/');
224*0Sstevel@tonic-gate if (node) {
225*0Sstevel@tonic-gate /*
226*0Sstevel@tonic-gate * user is now just the user portion and node
227*0Sstevel@tonic-gate * points to the start of the node part.
228*0Sstevel@tonic-gate */
229*0Sstevel@tonic-gate *node++ = '\0';
230*0Sstevel@tonic-gate
231*0Sstevel@tonic-gate /* Now see if there is a domain */
232*0Sstevel@tonic-gate domain = strchr(node, '@');
233*0Sstevel@tonic-gate }
234*0Sstevel@tonic-gate else
235*0Sstevel@tonic-gate /* Check for a domain */
236*0Sstevel@tonic-gate domain = strchr(user, '@');
237*0Sstevel@tonic-gate
238*0Sstevel@tonic-gate /* Set domain to the beginning of the domain part if pressent */
239*0Sstevel@tonic-gate if (domain)
240*0Sstevel@tonic-gate *domain++ = '\0';
241*0Sstevel@tonic-gate
242*0Sstevel@tonic-gate /*
243*0Sstevel@tonic-gate * See if the node part is important. If the user is root get
244*0Sstevel@tonic-gate * the host from the node. If node is not present we assume
245*0Sstevel@tonic-gate * we're the local host.
246*0Sstevel@tonic-gate */
247*0Sstevel@tonic-gate if (strcmp(user, "root") == 0) {
248*0Sstevel@tonic-gate char *dot;
249*0Sstevel@tonic-gate
250*0Sstevel@tonic-gate /*
251*0Sstevel@tonic-gate * We only want the host part of a qualfied host name. We
252*0Sstevel@tonic-gate * assume the domain part of a hostname is a DNS domain,
253*0Sstevel@tonic-gate * not an rpc domain. The rpc domain can be specified
254*0Sstevel@tonic-gate * in the optional security domain part.
255*0Sstevel@tonic-gate */
256*0Sstevel@tonic-gate if (node) {
257*0Sstevel@tonic-gate dot = strchr(node, '.');
258*0Sstevel@tonic-gate if (dot)
259*0Sstevel@tonic-gate *dot = '\0';
260*0Sstevel@tonic-gate }
261*0Sstevel@tonic-gate /*
262*0Sstevel@tonic-gate * If node is null, assume local host. If domain is
263*0Sstevel@tonic-gate * null assume local domain. See host2netname(3N)
264*0Sstevel@tonic-gate */
265*0Sstevel@tonic-gate if (!host2netname(netname, node, domain)) {
266*0Sstevel@tonic-gate *minor = DH_NETNAME_FAILURE;
267*0Sstevel@tonic-gate free(user);
268*0Sstevel@tonic-gate return (GSS_S_FAILURE);
269*0Sstevel@tonic-gate }
270*0Sstevel@tonic-gate free(user);
271*0Sstevel@tonic-gate return (do_netname_nametype(minor, netname, output));
272*0Sstevel@tonic-gate }
273*0Sstevel@tonic-gate
274*0Sstevel@tonic-gate /*
275*0Sstevel@tonic-gate * We use getpwnam_r to convert the name to uid. Note it is
276*0Sstevel@tonic-gate * important to use getpwnam_r to preserve MT safty.
277*0Sstevel@tonic-gate */
278*0Sstevel@tonic-gate if (getpwnam_r(user, &pwd, buff, sizeof (buff)) == NULL) {
279*0Sstevel@tonic-gate *minor = DH_NO_SUCH_USER;
280*0Sstevel@tonic-gate free(user);
281*0Sstevel@tonic-gate return (GSS_S_FAILURE);
282*0Sstevel@tonic-gate }
283*0Sstevel@tonic-gate
284*0Sstevel@tonic-gate /* If domain is null assume local domain. See user2netname(3N) */
285*0Sstevel@tonic-gate if (!user2netname(netname, pwd.pw_uid, domain)) {
286*0Sstevel@tonic-gate *minor = DH_NETNAME_FAILURE;
287*0Sstevel@tonic-gate free(user);
288*0Sstevel@tonic-gate return (GSS_S_FAILURE);
289*0Sstevel@tonic-gate }
290*0Sstevel@tonic-gate free(user);
291*0Sstevel@tonic-gate return (do_netname_nametype(minor, netname, output));
292*0Sstevel@tonic-gate }
293*0Sstevel@tonic-gate
294*0Sstevel@tonic-gate /*
295*0Sstevel@tonic-gate * do_hostbase_nametype convert a hostbase service name of the form
296*0Sstevel@tonic-gate * service@hostname.
297*0Sstevel@tonic-gate *
298*0Sstevel@tonic-gate * For Diffie-Hellman we assume that the service is running with the
299*0Sstevel@tonic-gate * credtials of the machine, i.e., as root.
300*0Sstevel@tonic-gate */
301*0Sstevel@tonic-gate static OM_uint32
do_hostbase_nametype(OM_uint32 * minor,char * input,gss_name_t * output)302*0Sstevel@tonic-gate do_hostbase_nametype(OM_uint32 *minor, char *input, gss_name_t *output)
303*0Sstevel@tonic-gate {
304*0Sstevel@tonic-gate /* Get the nostname */
305*0Sstevel@tonic-gate char *host = strchr(input, '@');
306*0Sstevel@tonic-gate char netname[MAXNETNAMELEN+1];
307*0Sstevel@tonic-gate
308*0Sstevel@tonic-gate
309*0Sstevel@tonic-gate /* If no host return bad name */
310*0Sstevel@tonic-gate if (host == NULL)
311*0Sstevel@tonic-gate return (GSS_S_BAD_NAME);
312*0Sstevel@tonic-gate
313*0Sstevel@tonic-gate /* Advance pass the "@" sign */
314*0Sstevel@tonic-gate host += 1;
315*0Sstevel@tonic-gate
316*0Sstevel@tonic-gate /* Convert the hostname to its netname */
317*0Sstevel@tonic-gate if (!host2netname(netname, host, NULL)) {
318*0Sstevel@tonic-gate *minor = DH_NETNAME_FAILURE;
319*0Sstevel@tonic-gate return (GSS_S_FAILURE);
320*0Sstevel@tonic-gate }
321*0Sstevel@tonic-gate
322*0Sstevel@tonic-gate /* Internalize the netname to output */
323*0Sstevel@tonic-gate return (do_netname_nametype(minor, netname, output));
324*0Sstevel@tonic-gate }
325*0Sstevel@tonic-gate
326*0Sstevel@tonic-gate /*
327*0Sstevel@tonic-gate * do_exported_netname: Convert an exported Diffie-Hellman name
328*0Sstevel@tonic-gate * to a Diffie-Hellman internal name.
329*0Sstevel@tonic-gate */
330*0Sstevel@tonic-gate static OM_uint32
do_exported_netname(dh_context_t ctx,OM_uint32 * minor,gss_buffer_t input,gss_name_t * output)331*0Sstevel@tonic-gate do_exported_netname(dh_context_t ctx, /* Diffie-Hellman mech context */
332*0Sstevel@tonic-gate OM_uint32 *minor, /* Mech status */
333*0Sstevel@tonic-gate gss_buffer_t input, /* The export name to convert */
334*0Sstevel@tonic-gate gss_name_t *output /* The converted internal name */)
335*0Sstevel@tonic-gate {
336*0Sstevel@tonic-gate /* All export names must start with this */
337*0Sstevel@tonic-gate const char tokid[] = "\x04\x01";
338*0Sstevel@tonic-gate const int tokid_len = 2;
339*0Sstevel@tonic-gate const int OIDlen_len = 2;
340*0Sstevel@tonic-gate const int namelen_len = 4;
341*0Sstevel@tonic-gate unsigned char *p = (unsigned char *)input->value;
342*0Sstevel@tonic-gate OM_uint32 len = input->length;
343*0Sstevel@tonic-gate int mechoidlen;
344*0Sstevel@tonic-gate OM_uint32 oidlen; /* includes object tag len & DER len bytes */
345*0Sstevel@tonic-gate OM_uint32 namelen;
346*0Sstevel@tonic-gate OM_uint32 currlen;
347*0Sstevel@tonic-gate OM_uint32 bytes;
348*0Sstevel@tonic-gate
349*0Sstevel@tonic-gate *minor = DH_BADARG_FAILURE;
350*0Sstevel@tonic-gate
351*0Sstevel@tonic-gate /* The len must be at least this big */
352*0Sstevel@tonic-gate if (len < tokid_len + OIDlen_len + namelen_len)
353*0Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN);
354*0Sstevel@tonic-gate
355*0Sstevel@tonic-gate /* Export names must start with the token id of 0x04 0x01 */
356*0Sstevel@tonic-gate if (memcmp(p, tokid, tokid_len) != 0)
357*0Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN);
358*0Sstevel@tonic-gate p += tokid_len;
359*0Sstevel@tonic-gate
360*0Sstevel@tonic-gate /* Decode the Mechanism oid */
361*0Sstevel@tonic-gate oidlen = (*p++ << 8) & 0xff00;
362*0Sstevel@tonic-gate oidlen |= *p++ & 0xff;
363*0Sstevel@tonic-gate
364*0Sstevel@tonic-gate /* Check that we actually have the mechanism oid elements */
365*0Sstevel@tonic-gate if (len < tokid_len + OIDlen_len + oidlen + namelen_len)
366*0Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN);
367*0Sstevel@tonic-gate
368*0Sstevel@tonic-gate /* Compare that the input is for this mechanism */
369*0Sstevel@tonic-gate if (*p++ != 0x06)
370*0Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN);
371*0Sstevel@tonic-gate currlen = len - (tokid_len + OIDlen_len + oidlen + namelen_len);
372*0Sstevel@tonic-gate if ((mechoidlen = get_der_length(&p, currlen, &bytes)) < 0)
373*0Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN);
374*0Sstevel@tonic-gate if (mechoidlen != ctx->mech->length)
375*0Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN);
376*0Sstevel@tonic-gate if (memcmp(p, ctx->mech->elements, mechoidlen) != 0)
377*0Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN);
378*0Sstevel@tonic-gate p += mechoidlen;
379*0Sstevel@tonic-gate
380*0Sstevel@tonic-gate /* Grab the length of the mechanism specific name per RFC 2078 */
381*0Sstevel@tonic-gate namelen = (*p++ << 24) & 0xff000000;
382*0Sstevel@tonic-gate namelen |= (*p++ << 16) & 0xff0000;
383*0Sstevel@tonic-gate namelen |= (*p++ << 8) & 0xff00;
384*0Sstevel@tonic-gate namelen |= *p++ & 0xff;
385*0Sstevel@tonic-gate
386*0Sstevel@tonic-gate /* This should alway be false */
387*0Sstevel@tonic-gate if (len < tokid_len + OIDlen_len + oidlen + namelen_len + namelen)
388*0Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN);
389*0Sstevel@tonic-gate
390*0Sstevel@tonic-gate /* Make sure the bytes for the netname oid length are available */
391*0Sstevel@tonic-gate if (namelen < OIDlen_len)
392*0Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN);
393*0Sstevel@tonic-gate
394*0Sstevel@tonic-gate /* Get the netname oid length */
395*0Sstevel@tonic-gate oidlen = (*p++ << 8) & 0xff00;
396*0Sstevel@tonic-gate oidlen = *p++ & 0xff;
397*0Sstevel@tonic-gate
398*0Sstevel@tonic-gate /* See if we have the elements of the netname oid */
399*0Sstevel@tonic-gate if (namelen < OIDlen_len + oidlen)
400*0Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN);
401*0Sstevel@tonic-gate
402*0Sstevel@tonic-gate /* Check that the oid is really a netname */
403*0Sstevel@tonic-gate if (oidlen != __DH_GSS_C_NT_NETNAME->length)
404*0Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN);
405*0Sstevel@tonic-gate if (memcmp(p, __DH_GSS_C_NT_NETNAME->elements,
406*0Sstevel@tonic-gate __DH_GSS_C_NT_NETNAME->length) != 0)
407*0Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN);
408*0Sstevel@tonic-gate
409*0Sstevel@tonic-gate /* p now points to the netname wich is null terminated */
410*0Sstevel@tonic-gate p += oidlen;
411*0Sstevel@tonic-gate
412*0Sstevel@tonic-gate /*
413*0Sstevel@tonic-gate * How the netname is encoded in an export name type for
414*0Sstevel@tonic-gate * this mechanism. See _dh_gss_export_name below.
415*0Sstevel@tonic-gate */
416*0Sstevel@tonic-gate
417*0Sstevel@tonic-gate if (namelen != OIDlen_len + oidlen + strlen((char *)p) + 1)
418*0Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN);
419*0Sstevel@tonic-gate
420*0Sstevel@tonic-gate /* Grab the netname */
421*0Sstevel@tonic-gate *output = (gss_name_t)strdup((char *)p);
422*0Sstevel@tonic-gate if (*output) {
423*0Sstevel@tonic-gate *minor = 0;
424*0Sstevel@tonic-gate return (GSS_S_COMPLETE);
425*0Sstevel@tonic-gate }
426*0Sstevel@tonic-gate
427*0Sstevel@tonic-gate *minor = DH_NOMEM_FAILURE;
428*0Sstevel@tonic-gate return (GSS_S_FAILURE);
429*0Sstevel@tonic-gate }
430*0Sstevel@tonic-gate
431*0Sstevel@tonic-gate /*
432*0Sstevel@tonic-gate * __dh_gss_import_name: Diffie-Hellman entry point for gss_import_name.
433*0Sstevel@tonic-gate * Given an input name of a specified name type, convert this to a
434*0Sstevel@tonic-gate * Diffie-Hellman internal name (netname).
435*0Sstevel@tonic-gate *
436*0Sstevel@tonic-gate * The idea here is simply compare the name_type supplied with each
437*0Sstevel@tonic-gate * name type that we know how to deal with. If we have a match we call
438*0Sstevel@tonic-gate * the appropriate support routine form above. If we done't have a match
439*0Sstevel@tonic-gate * we return GSS_S_BAD_NAMETYPE
440*0Sstevel@tonic-gate */
441*0Sstevel@tonic-gate OM_uint32
__dh_gss_import_name(void * ctx,OM_uint32 * minor,gss_buffer_t input,gss_OID name_type,gss_name_t * output)442*0Sstevel@tonic-gate __dh_gss_import_name(void *ctx, /* Per mechanism context */
443*0Sstevel@tonic-gate OM_uint32 *minor, /* Mechanism status */
444*0Sstevel@tonic-gate gss_buffer_t input, /* The name to convert */
445*0Sstevel@tonic-gate gss_OID name_type, /* of this name_type */
446*0Sstevel@tonic-gate gss_name_t *output /* The converted name */)
447*0Sstevel@tonic-gate {
448*0Sstevel@tonic-gate char *name;
449*0Sstevel@tonic-gate OM_uint32 stat;
450*0Sstevel@tonic-gate
451*0Sstevel@tonic-gate if (minor == NULL || output == NULL)
452*0Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE);
453*0Sstevel@tonic-gate
454*0Sstevel@tonic-gate if (input == NULL || input->value == NULL)
455*0Sstevel@tonic-gate return (GSS_S_BAD_NAME | GSS_S_CALL_INACCESSIBLE_READ);
456*0Sstevel@tonic-gate if (name_type == GSS_C_NO_OID)
457*0Sstevel@tonic-gate return (GSS_S_BAD_NAMETYPE);
458*0Sstevel@tonic-gate
459*0Sstevel@tonic-gate /* Set sane state */
460*0Sstevel@tonic-gate *minor = DH_SUCCESS;
461*0Sstevel@tonic-gate *output = GSS_C_NO_NAME;
462*0Sstevel@tonic-gate
463*0Sstevel@tonic-gate /* UID in machine format */
464*0Sstevel@tonic-gate if (__OID_equal(name_type, GSS_C_NT_MACHINE_UID_NAME)) {
465*0Sstevel@tonic-gate uid_t uid;
466*0Sstevel@tonic-gate if (input->length != sizeof (uid_t))
467*0Sstevel@tonic-gate return (GSS_S_BAD_NAME);
468*0Sstevel@tonic-gate uid = *(uid_t *)input->value;
469*0Sstevel@tonic-gate /* Should we assume that the id is network byte order ??? */
470*0Sstevel@tonic-gate /* uid = htonl(uid); No, this should be the local orfering */
471*0Sstevel@tonic-gate return (do_uid_nametype(minor, uid, output));
472*0Sstevel@tonic-gate
473*0Sstevel@tonic-gate /* Name that was exported with __dh_gss_export_name */
474*0Sstevel@tonic-gate } else if (__OID_equal(name_type, GSS_C_NT_EXPORT_NAME)) {
475*0Sstevel@tonic-gate stat = do_exported_netname((dh_context_t)ctx, minor,
476*0Sstevel@tonic-gate input, output);
477*0Sstevel@tonic-gate return (stat);
478*0Sstevel@tonic-gate }
479*0Sstevel@tonic-gate
480*0Sstevel@tonic-gate /* Null ternamte name so we can manipulate as a c-style string */
481*0Sstevel@tonic-gate name = malloc(input->length+1);
482*0Sstevel@tonic-gate if (name == NULL) {
483*0Sstevel@tonic-gate *minor = DH_NOMEM_FAILURE;
484*0Sstevel@tonic-gate return (GSS_S_FAILURE);
485*0Sstevel@tonic-gate }
486*0Sstevel@tonic-gate memcpy(name, input->value, input->length);
487*0Sstevel@tonic-gate name[input->length] = '\0';
488*0Sstevel@tonic-gate
489*0Sstevel@tonic-gate
490*0Sstevel@tonic-gate /* Diffie-Hellman (ONC RPC netname) */
491*0Sstevel@tonic-gate if (__OID_equal(name_type, __DH_GSS_C_NT_NETNAME)) {
492*0Sstevel@tonic-gate stat = do_netname_nametype(minor, name, output);
493*0Sstevel@tonic-gate free(name);
494*0Sstevel@tonic-gate return (stat);
495*0Sstevel@tonic-gate /* Host based service name (service@hostname) */
496*0Sstevel@tonic-gate } else if (__OID_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE)) {
497*0Sstevel@tonic-gate stat = do_hostbase_nametype(minor, name, output);
498*0Sstevel@tonic-gate free(name);
499*0Sstevel@tonic-gate return (stat);
500*0Sstevel@tonic-gate /* Thus local OS user name */
501*0Sstevel@tonic-gate } else if (__OID_equal(name_type, GSS_C_NT_USER_NAME)) {
502*0Sstevel@tonic-gate stat = do_username_nametype(minor, name, output);
503*0Sstevel@tonic-gate free(name);
504*0Sstevel@tonic-gate return (stat);
505*0Sstevel@tonic-gate /* The os user id writen as a string */
506*0Sstevel@tonic-gate } else if (__OID_equal(name_type, GSS_C_NT_STRING_UID_NAME)) {
507*0Sstevel@tonic-gate char *p;
508*0Sstevel@tonic-gate /* Convert the name to a uid */
509*0Sstevel@tonic-gate uid_t uid = (uid_t)strtol(name, &p, 0);
510*0Sstevel@tonic-gate free(name);
511*0Sstevel@tonic-gate if (*p != '\0')
512*0Sstevel@tonic-gate return (GSS_S_BAD_NAME);
513*0Sstevel@tonic-gate return (do_uid_nametype(minor, uid, output));
514*0Sstevel@tonic-gate } else {
515*0Sstevel@tonic-gate /* Any thing else */
516*0Sstevel@tonic-gate free(name);
517*0Sstevel@tonic-gate return (GSS_S_BAD_NAMETYPE);
518*0Sstevel@tonic-gate }
519*0Sstevel@tonic-gate }
520*0Sstevel@tonic-gate
521*0Sstevel@tonic-gate /*
522*0Sstevel@tonic-gate * __dh_gss_release_name: DH entry point for gss_release_name.
523*0Sstevel@tonic-gate * Release an internal DH name.
524*0Sstevel@tonic-gate */
525*0Sstevel@tonic-gate OM_uint32
__dh_gss_release_name(void * ctx,OM_uint32 * minor,gss_name_t * name)526*0Sstevel@tonic-gate __dh_gss_release_name(void *ctx, OM_uint32 *minor, gss_name_t *name)
527*0Sstevel@tonic-gate {
528*0Sstevel@tonic-gate _NOTE(ARGUNUSED(ctx))
529*0Sstevel@tonic-gate
530*0Sstevel@tonic-gate if (minor == 0 || name == 0)
531*0Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE);
532*0Sstevel@tonic-gate
533*0Sstevel@tonic-gate *minor = DH_SUCCESS;
534*0Sstevel@tonic-gate
535*0Sstevel@tonic-gate free(*name);
536*0Sstevel@tonic-gate *name = GSS_C_NO_NAME;
537*0Sstevel@tonic-gate
538*0Sstevel@tonic-gate return (GSS_S_COMPLETE);
539*0Sstevel@tonic-gate }
540*0Sstevel@tonic-gate
541*0Sstevel@tonic-gate /* Lock for initializing oid_name_tab */
542*0Sstevel@tonic-gate static mutex_t name_tab_lock = DEFAULTMUTEX;
543*0Sstevel@tonic-gate
544*0Sstevel@tonic-gate /* Table of name types that this mechanism understands */
545*0Sstevel@tonic-gate static const gss_OID_desc * oid_name_tab[OID_MAX_NAME_ENTRIES];
546*0Sstevel@tonic-gate
547*0Sstevel@tonic-gate /*
548*0Sstevel@tonic-gate * __dh_gss_inquire_names_for_mech: DH entry point for
549*0Sstevel@tonic-gate * gss_inquire_names_for_mech.
550*0Sstevel@tonic-gate *
551*0Sstevel@tonic-gate * Return a set of OID name types that a mechanism can understand
552*0Sstevel@tonic-gate */
553*0Sstevel@tonic-gate OM_uint32
__dh_gss_inquire_names_for_mech(void * ctx,OM_uint32 * minor,gss_OID mech,gss_OID_set * names)554*0Sstevel@tonic-gate __dh_gss_inquire_names_for_mech(void *ctx, OM_uint32 *minor,
555*0Sstevel@tonic-gate gss_OID mech, gss_OID_set *names)
556*0Sstevel@tonic-gate {
557*0Sstevel@tonic-gate _NOTE(ARGUNUSED(ctx,mech))
558*0Sstevel@tonic-gate
559*0Sstevel@tonic-gate /* See if we need to initialize the table */
560*0Sstevel@tonic-gate if (oid_name_tab[0] == 0) {
561*0Sstevel@tonic-gate mutex_lock(&name_tab_lock);
562*0Sstevel@tonic-gate /* If nobody sneaked in, initialize the table */
563*0Sstevel@tonic-gate if (oid_name_tab[0] == 0) {
564*0Sstevel@tonic-gate oid_name_tab[0] = __DH_GSS_C_NT_NETNAME;
565*0Sstevel@tonic-gate oid_name_tab[1] = GSS_C_NT_HOSTBASED_SERVICE;
566*0Sstevel@tonic-gate oid_name_tab[2] = GSS_C_NT_USER_NAME;
567*0Sstevel@tonic-gate oid_name_tab[3] = GSS_C_NT_MACHINE_UID_NAME;
568*0Sstevel@tonic-gate oid_name_tab[4] = GSS_C_NT_STRING_UID_NAME;
569*0Sstevel@tonic-gate oid_name_tab[5] = GSS_C_NT_EXPORT_NAME;
570*0Sstevel@tonic-gate /* oid_name_tab[6] = GSS_C_NT_ANONYMOUS_NAME; */
571*0Sstevel@tonic-gate }
572*0Sstevel@tonic-gate mutex_unlock(&name_tab_lock);
573*0Sstevel@tonic-gate }
574*0Sstevel@tonic-gate
575*0Sstevel@tonic-gate /* Return the set of OIDS from the table */
576*0Sstevel@tonic-gate if ((*minor = __OID_copy_set_from_array(names,
577*0Sstevel@tonic-gate oid_name_tab, 6)) != DH_SUCCESS)
578*0Sstevel@tonic-gate return (GSS_S_FAILURE);
579*0Sstevel@tonic-gate
580*0Sstevel@tonic-gate return (GSS_S_COMPLETE);
581*0Sstevel@tonic-gate }
582*0Sstevel@tonic-gate
583*0Sstevel@tonic-gate
584*0Sstevel@tonic-gate /*
585*0Sstevel@tonic-gate * Private libgss entry point to convert a principal name to uid.
586*0Sstevel@tonic-gate */
587*0Sstevel@tonic-gate OM_uint32
__dh_pname_to_uid(void * ctx,OM_uint32 * minor,const gss_name_t pname,uid_t * uid)588*0Sstevel@tonic-gate __dh_pname_to_uid(void *ctx, /* DH mech context (not used) */
589*0Sstevel@tonic-gate OM_uint32 *minor, /* Mech status */
590*0Sstevel@tonic-gate const gss_name_t pname, /* principal */
591*0Sstevel@tonic-gate uid_t *uid /* where to put the uid */)
592*0Sstevel@tonic-gate {
593*0Sstevel@tonic-gate _NOTE(ARGUNUSED(ctx))
594*0Sstevel@tonic-gate
595*0Sstevel@tonic-gate gid_t gid;
596*0Sstevel@tonic-gate gid_t glist[NGRPS];
597*0Sstevel@tonic-gate int glen;
598*0Sstevel@tonic-gate /* Convert the principal name to a netname */
599*0Sstevel@tonic-gate char *netname = (char *)pname;
600*0Sstevel@tonic-gate char host_netname[MAXNETNAMELEN+1];
601*0Sstevel@tonic-gate
602*0Sstevel@tonic-gate if (pname == 0)
603*0Sstevel@tonic-gate return (GSS_S_BAD_NAME | GSS_S_CALL_INACCESSIBLE_READ);
604*0Sstevel@tonic-gate if (minor == 0 || uid == 0)
605*0Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE);
606*0Sstevel@tonic-gate
607*0Sstevel@tonic-gate *minor = DH_SUCCESS;
608*0Sstevel@tonic-gate *uid = UID_NOBODY;
609*0Sstevel@tonic-gate
610*0Sstevel@tonic-gate /* First try to convert as a user */
611*0Sstevel@tonic-gate if (netname2user(netname, uid, &gid, &glen, glist))
612*0Sstevel@tonic-gate return (GSS_S_COMPLETE);
613*0Sstevel@tonic-gate /* Get this hosts netname */
614*0Sstevel@tonic-gate else if (host2netname(host_netname, NULL, NULL)) {
615*0Sstevel@tonic-gate /*
616*0Sstevel@tonic-gate * If the netname is this host's netname then we're root
617*0Sstevel@tonic-gate * else we're nobody.
618*0Sstevel@tonic-gate */
619*0Sstevel@tonic-gate if (strncmp(netname, host_netname, MAXNETNAMELEN) == 0)
620*0Sstevel@tonic-gate *uid = 0;
621*0Sstevel@tonic-gate return (GSS_S_COMPLETE);
622*0Sstevel@tonic-gate }
623*0Sstevel@tonic-gate
624*0Sstevel@tonic-gate /* We could not get a netname */
625*0Sstevel@tonic-gate *minor = DH_NETNAME_FAILURE;
626*0Sstevel@tonic-gate return (GSS_S_FAILURE);
627*0Sstevel@tonic-gate }
628*0Sstevel@tonic-gate
629*0Sstevel@tonic-gate /*
630*0Sstevel@tonic-gate * __dh_gss_export_name: Diffie-Hellman support for gss_export_name.
631*0Sstevel@tonic-gate * Given a Diffie-Hellman internal name return the GSS exported format.
632*0Sstevel@tonic-gate */
633*0Sstevel@tonic-gate OM_uint32
__dh_gss_export_name(void * ctx,OM_uint32 * minor,const gss_name_t input_name,gss_buffer_t exported_name)634*0Sstevel@tonic-gate __dh_gss_export_name(void *ctx, /* Per mechanism context */
635*0Sstevel@tonic-gate OM_uint32 *minor, /* Mechanism status */
636*0Sstevel@tonic-gate const gss_name_t input_name, /* The name to export */
637*0Sstevel@tonic-gate gss_buffer_t exported_name /* Exported name goes here */)
638*0Sstevel@tonic-gate {
639*0Sstevel@tonic-gate /* input_name is dh principal name */
640*0Sstevel@tonic-gate dh_principal pname = (dh_principal)input_name;
641*0Sstevel@tonic-gate dh_context_t dc = (dh_context_t)ctx;
642*0Sstevel@tonic-gate /* Magic for exported blobs */
643*0Sstevel@tonic-gate const char tokid[] = "\x04\x01";
644*0Sstevel@tonic-gate const int tokid_len = 2;
645*0Sstevel@tonic-gate const int OIDlen_len = 2; /* Why did they do this? */
646*0Sstevel@tonic-gate const int namelen_len = 4;
647*0Sstevel@tonic-gate const int mechoid_tag_len = 1;
648*0Sstevel@tonic-gate unsigned char *p;
649*0Sstevel@tonic-gate OM_uint32 len;
650*0Sstevel@tonic-gate OM_uint32 namelen;
651*0Sstevel@tonic-gate OM_uint32 currlen;
652*0Sstevel@tonic-gate OM_uint32 oid_der_len = 0;
653*0Sstevel@tonic-gate
654*0Sstevel@tonic-gate if (minor == 0 || exported_name == GSS_C_NO_BUFFER)
655*0Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE);
656*0Sstevel@tonic-gate if (input_name == GSS_C_NO_NAME)
657*0Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_READ);
658*0Sstevel@tonic-gate
659*0Sstevel@tonic-gate /* Set sane outputs */
660*0Sstevel@tonic-gate *minor = DH_SUCCESS;
661*0Sstevel@tonic-gate exported_name->length = 0;
662*0Sstevel@tonic-gate exported_name->value = NULL;
663*0Sstevel@tonic-gate
664*0Sstevel@tonic-gate /* Determine the length of the name */
665*0Sstevel@tonic-gate namelen = OIDlen_len + __DH_GSS_C_NT_NETNAME->length
666*0Sstevel@tonic-gate + strlen(pname)+1;
667*0Sstevel@tonic-gate oid_der_len = der_length_size(dc->mech->length);
668*0Sstevel@tonic-gate /* Find the total length */
669*0Sstevel@tonic-gate len = tokid_len + OIDlen_len + mechoid_tag_len + oid_der_len
670*0Sstevel@tonic-gate + dc->mech->length + namelen_len + namelen;
671*0Sstevel@tonic-gate
672*0Sstevel@tonic-gate /* Allocate the blob */
673*0Sstevel@tonic-gate p = New(unsigned char, len);
674*0Sstevel@tonic-gate if (p == NULL) {
675*0Sstevel@tonic-gate *minor = DH_NOMEM_FAILURE;
676*0Sstevel@tonic-gate return (GSS_S_FAILURE);
677*0Sstevel@tonic-gate }
678*0Sstevel@tonic-gate /* Set the blob to the exported name */
679*0Sstevel@tonic-gate exported_name->length = len;
680*0Sstevel@tonic-gate exported_name->value = p;
681*0Sstevel@tonic-gate
682*0Sstevel@tonic-gate /* Start with some magic */
683*0Sstevel@tonic-gate memcpy(p, tokid, tokid_len);
684*0Sstevel@tonic-gate p += tokid_len;
685*0Sstevel@tonic-gate
686*0Sstevel@tonic-gate /*
687*0Sstevel@tonic-gate * The spec only allows two bytes for the oid length.
688*0Sstevel@tonic-gate * We are assuming here that the correct encodeing is MSB first as
689*0Sstevel@tonic-gate * was done in libgss.
690*0Sstevel@tonic-gate */
691*0Sstevel@tonic-gate
692*0Sstevel@tonic-gate *p++ = ((mechoid_tag_len + oid_der_len + dc->mech->length)
693*0Sstevel@tonic-gate & 0xff00) >> 8;
694*0Sstevel@tonic-gate *p++ = ((mechoid_tag_len + oid_der_len + dc->mech->length)
695*0Sstevel@tonic-gate & 0x00ff);
696*0Sstevel@tonic-gate
697*0Sstevel@tonic-gate /* Now the mechanism OID DER Encoding */
698*0Sstevel@tonic-gate *p++ = 0x06; /* Universal Tag for OID */
699*0Sstevel@tonic-gate currlen = len - tokid_len - OIDlen_len - mechoid_tag_len;
700*0Sstevel@tonic-gate if (!put_der_length(dc->mech->length, &p, currlen) == 0) {
701*0Sstevel@tonic-gate return (GSS_S_FAILURE);
702*0Sstevel@tonic-gate }
703*0Sstevel@tonic-gate
704*0Sstevel@tonic-gate /* Now the mechanism OID elements */
705*0Sstevel@tonic-gate memcpy(p, dc->mech->elements, dc->mech->length);
706*0Sstevel@tonic-gate p += dc->mech->length;
707*0Sstevel@tonic-gate
708*0Sstevel@tonic-gate /* The name length most MSB first */
709*0Sstevel@tonic-gate *p++ = (namelen & 0xff000000) >> 24;
710*0Sstevel@tonic-gate *p++ = (namelen & 0x00ff0000) >> 16;
711*0Sstevel@tonic-gate *p++ = (namelen & 0x0000ff00) >> 8;
712*0Sstevel@tonic-gate *p++ = (namelen & 0x000000ff);
713*0Sstevel@tonic-gate
714*0Sstevel@tonic-gate /*
715*0Sstevel@tonic-gate * We'll now encode the netname oid. Again we'll just use 2 bytes.
716*0Sstevel@tonic-gate * This is the same encoding that the libgss implementor uses, so
717*0Sstevel@tonic-gate * we'll just follow along.
718*0Sstevel@tonic-gate */
719*0Sstevel@tonic-gate
720*0Sstevel@tonic-gate *p++ = (__DH_GSS_C_NT_NETNAME->length & 0xff00) >> 8;
721*0Sstevel@tonic-gate *p++ = (__DH_GSS_C_NT_NETNAME->length &0x00ff);
722*0Sstevel@tonic-gate
723*0Sstevel@tonic-gate /* The netname oid values */
724*0Sstevel@tonic-gate memcpy(p, __DH_GSS_C_NT_NETNAME->elements,
725*0Sstevel@tonic-gate __DH_GSS_C_NT_NETNAME->length);
726*0Sstevel@tonic-gate
727*0Sstevel@tonic-gate p += __DH_GSS_C_NT_NETNAME->length;
728*0Sstevel@tonic-gate
729*0Sstevel@tonic-gate /* Now we copy the netname including the null byte to be safe */
730*0Sstevel@tonic-gate memcpy(p, pname, strlen(pname) + 1);
731*0Sstevel@tonic-gate
732*0Sstevel@tonic-gate return (GSS_S_COMPLETE);
733*0Sstevel@tonic-gate }
734*0Sstevel@tonic-gate
735*0Sstevel@tonic-gate /*
736*0Sstevel@tonic-gate * Support routine for __dh_internal_release_oid. Return True if
737*0Sstevel@tonic-gate * the supplied OID points to the reference OID or if the elements
738*0Sstevel@tonic-gate * of the reference OID are the same as the supplied OID. In the
739*0Sstevel@tonic-gate * latter case, just free the OID container and set the pointer to it
740*0Sstevel@tonic-gate * to GSS_C_NO_OID. Otherwise return false
741*0Sstevel@tonic-gate */
742*0Sstevel@tonic-gate static int
release_oid(const gss_OID_desc * const ref,gss_OID * oid)743*0Sstevel@tonic-gate release_oid(const gss_OID_desc * const ref, gss_OID *oid)
744*0Sstevel@tonic-gate {
745*0Sstevel@tonic-gate gss_OID id = *oid;
746*0Sstevel@tonic-gate
747*0Sstevel@tonic-gate if (id == ref)
748*0Sstevel@tonic-gate return (TRUE);
749*0Sstevel@tonic-gate
750*0Sstevel@tonic-gate /*
751*0Sstevel@tonic-gate * If some on create a shallow copy free, the structure point to
752*0Sstevel@tonic-gate * id and set the pointer to it to GSS_C_NO_OID
753*0Sstevel@tonic-gate */
754*0Sstevel@tonic-gate if (id->elements == ref->elements) {
755*0Sstevel@tonic-gate Free(id);
756*0Sstevel@tonic-gate *oid = GSS_C_NO_OID;
757*0Sstevel@tonic-gate return (TRUE);
758*0Sstevel@tonic-gate }
759*0Sstevel@tonic-gate
760*0Sstevel@tonic-gate return (FALSE);
761*0Sstevel@tonic-gate }
762*0Sstevel@tonic-gate
763*0Sstevel@tonic-gate /*
764*0Sstevel@tonic-gate * __dh_gss_internal_release_oid: DH support for the gss_internal_relaese_oid
765*0Sstevel@tonic-gate * entry. Check that the refence to an oid is one of our mechanisms static
766*0Sstevel@tonic-gate * OIDS. If it is return true indicating to libgss that we have handled the
767*0Sstevel@tonic-gate * release of that OID. Otherwise we return false and let libgss deal with it.
768*0Sstevel@tonic-gate *
769*0Sstevel@tonic-gate * The only OIDS we know are the calling mechanism found in the context
770*0Sstevel@tonic-gate * and the shared DH_GSS_C_NT_NETNAME name type
771*0Sstevel@tonic-gate */
772*0Sstevel@tonic-gate OM_uint32
__dh_gss_internal_release_oid(void * ctx,OM_uint32 * minor,gss_OID * oid)773*0Sstevel@tonic-gate __dh_gss_internal_release_oid(void *ctx, OM_uint32 *minor, gss_OID *oid)
774*0Sstevel@tonic-gate {
775*0Sstevel@tonic-gate dh_context_t dhcxt = (dh_context_t)ctx;
776*0Sstevel@tonic-gate
777*0Sstevel@tonic-gate if (minor == 0)
778*0Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE);
779*0Sstevel@tonic-gate
780*0Sstevel@tonic-gate *minor = DH_SUCCESS;
781*0Sstevel@tonic-gate
782*0Sstevel@tonic-gate if (oid == NULL || *oid == NULL)
783*0Sstevel@tonic-gate return (GSS_S_COMPLETE);
784*0Sstevel@tonic-gate
785*0Sstevel@tonic-gate if (release_oid(dhcxt->mech, oid))
786*0Sstevel@tonic-gate return (GSS_S_COMPLETE);
787*0Sstevel@tonic-gate
788*0Sstevel@tonic-gate if (release_oid(__DH_GSS_C_NT_NETNAME, oid))
789*0Sstevel@tonic-gate return (GSS_S_COMPLETE);
790*0Sstevel@tonic-gate
791*0Sstevel@tonic-gate return (GSS_S_FAILURE);
792*0Sstevel@tonic-gate }
793