8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / gss_mechs / mech_dh / backend / mech / name.c
blob6ccb78fe51a8162815cb2c6e90d7e2fbdb2f11d7
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 * name.c
25 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
30 #pragma ident "%Z%%M% %I% %E% SMI"
32 #include "dh_gssapi.h"
33 #include <pwd.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/note.h>
39 #include <thread.h>
41 extern int
42 get_der_length(unsigned char **, unsigned int, unsigned int *);
44 extern unsigned int
45 der_length_size(unsigned int);
47 extern int
48 put_der_length(unsigned int, unsigned char **, unsigned int);
50 /* Diffie-Hellman ONC RPC netname name type */
51 static gss_OID_desc __DH_GSS_C_NT_NETNAME_desc =
52 { 9, "\053\006\004\001\052\002\032\001\001" };
54 const gss_OID_desc * const __DH_GSS_C_NT_NETNAME = &__DH_GSS_C_NT_NETNAME_desc;
56 #define OID_MAX_NAME_ENTRIES 32
59 * __dh_gss_compare_name: Diffie-Hellman machanism support for
60 * gss_compare_name. Given two gss_name_ts that are presumed to
61 * be rpc netnames set the *equal parameter to true if they are
62 * the same, else set it to false.
65 OM_uint32
66 __dh_gss_compare_name(void *ctx, /* Per mechanism context (not used) */
67 OM_uint32 *minor, /* Mechanism status */
68 gss_name_t name1, /* First name to compare */
69 gss_name_t name2, /* Second name to compare */
70 int *equal /* The result */)
72 _NOTE(ARGUNUSED(ctx))
74 if (minor == 0 || equal == 0)
75 return (GSS_S_CALL_INACCESSIBLE_WRITE);
77 *minor = DH_SUCCESS;
79 if (name1 == 0 || name2 == 0) {
80 *minor = DH_BADARG_FAILURE;
81 return (GSS_S_BAD_NAME | GSS_S_CALL_INACCESSIBLE_READ);
84 *equal = (strcmp((char *)name1, (char *)name2) == 0);
86 return (GSS_S_COMPLETE);
90 * __dh_gss_display_name: Supports gss_display_name for Diffie-Hellman
91 * mechanism. This takes a gss internal name and converts it to
92 * a counted string suitable for display.
94 OM_uint32
95 __dh_gss_display_name(void * ctx, /* Per mechanism context (not used) */
96 OM_uint32* minor, /* Mechanism status */
97 gss_name_t name, /* Diffie-Hellman internal name */
98 gss_buffer_t output, /* Were the printable name goes */
99 gss_OID *name_type /* Name type of the internal name */)
101 _NOTE(ARGUNUSED(ctx))
103 if (minor == 0 || output == 0)
104 return (GSS_S_CALL_INACCESSIBLE_WRITE);
106 if (name == 0)
107 return (GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME);
109 *minor = DH_SUCCESS;
111 output->length = 0;
112 output->value = (void *)strdup((char *)name);
113 if (output->value == NULL) {
114 *minor = DH_NOMEM_FAILURE;
115 return (GSS_S_FAILURE);
117 output->length = strlen((char *)name) + 1;
120 * Note: we no longer copy the name type OID. The current draft of
121 * the standard specifies:
123 * "The returned gss_OID will be a pointer into static stoarge
124 * and should be treated as read-only by the caller (in particular,
125 * it does not need to be freed)."
127 * if (name_type) {
128 * if ((*minor = __OID_copy(name_type, __DH_GSS_C_NT_NETNAME))
129 * != DH_SUCCESS) {
130 * free(output->value);
131 * output->value = NULL;
132 * return (GSS_S_FAILURE);
137 if (name_type)
138 *name_type = (gss_OID) __DH_GSS_C_NT_NETNAME;
140 return (GSS_S_COMPLETE);
144 * Routine that takes a netname as a character string and assigns it
145 * to a an gss_name_t pointed to by output.
147 static OM_uint32
148 do_netname_nametype(OM_uint32 *minor, char *input, gss_name_t *output)
150 if (__dh_validate_principal(input) != DH_SUCCESS)
151 return (GSS_S_BAD_NAME);
153 *minor = DH_SUCCESS;
154 *output = (gss_name_t)strdup((char *)input);
156 if (*output == NULL) {
157 *minor = DH_NOMEM_FAILURE;
158 return (GSS_S_FAILURE);
161 return (GSS_S_COMPLETE);
165 * do_uid_nametype converts a uid to a gss_name_t pointed to by output
167 static OM_uint32
168 do_uid_nametype(OM_uint32 *minor, uid_t uid, gss_name_t *output)
170 char netname[MAXNETNAMELEN+1];
172 if (!user2netname(netname, uid, NULL)) {
173 *minor = DH_NETNAME_FAILURE;
174 return (GSS_S_FAILURE);
176 return (do_netname_nametype(minor, netname, output));
180 * do_username_nametype converts a username to a gss_name_t pointed to by
181 * output.
183 * A username will be represented by the following:
184 * name[/node][@security-domain]
186 * Then optional security-domain will represent secure rpc domain if
187 * present. If not present the local domain will be used. name is the
188 * user name as found in the unix password file. If name is root and
189 * node is present, then node will represent the host. If the host is
190 * a qualified name we assume that it is a DNS name and will only return
191 * the first commponnet since we want host name that are relative to
192 * the security domain (secure rpc domain).
195 static OM_uint32
196 do_username_nametype(OM_uint32 *minor, char *uname, gss_name_t *output)
198 char netname[MAXNETNAMELEN+1];
199 char *user, *node, *domain;
200 struct passwd pwd;
201 char buff[1024];
203 /* Set outputs to sane values */
205 *output = 0;
206 *minor = DH_SUCCESS;
208 /* See if we have a name */
209 if (uname == 0) {
210 *minor = DH_NO_SUCH_USER;
211 return (GSS_S_FAILURE);
214 /* copy the name so that we can do surgery on it */
215 user = strdup(uname);
216 if (user == 0) {
217 *minor = DH_NOMEM_FAILURE;
218 return (GSS_S_FAILURE);
222 /* Look for optional node part */
223 node = strchr(user, '/');
224 if (node) {
226 * user is now just the user portion and node
227 * points to the start of the node part.
229 *node++ = '\0';
231 /* Now see if there is a domain */
232 domain = strchr(node, '@');
234 else
235 /* Check for a domain */
236 domain = strchr(user, '@');
238 /* Set domain to the beginning of the domain part if pressent */
239 if (domain)
240 *domain++ = '\0';
243 * See if the node part is important. If the user is root get
244 * the host from the node. If node is not present we assume
245 * we're the local host.
247 if (strcmp(user, "root") == 0) {
248 char *dot;
251 * We only want the host part of a qualfied host name. We
252 * assume the domain part of a hostname is a DNS domain,
253 * not an rpc domain. The rpc domain can be specified
254 * in the optional security domain part.
256 if (node) {
257 dot = strchr(node, '.');
258 if (dot)
259 *dot = '\0';
262 * If node is null, assume local host. If domain is
263 * null assume local domain. See host2netname(3N)
265 if (!host2netname(netname, node, domain)) {
266 *minor = DH_NETNAME_FAILURE;
267 free(user);
268 return (GSS_S_FAILURE);
270 free(user);
271 return (do_netname_nametype(minor, netname, output));
275 * We use getpwnam_r to convert the name to uid. Note it is
276 * important to use getpwnam_r to preserve MT safty.
278 if (getpwnam_r(user, &pwd, buff, sizeof (buff)) == NULL) {
279 *minor = DH_NO_SUCH_USER;
280 free(user);
281 return (GSS_S_FAILURE);
284 /* If domain is null assume local domain. See user2netname(3N) */
285 if (!user2netname(netname, pwd.pw_uid, domain)) {
286 *minor = DH_NETNAME_FAILURE;
287 free(user);
288 return (GSS_S_FAILURE);
290 free(user);
291 return (do_netname_nametype(minor, netname, output));
295 * do_hostbase_nametype convert a hostbase service name of the form
296 * service@hostname.
298 * For Diffie-Hellman we assume that the service is running with the
299 * credtials of the machine, i.e., as root.
301 static OM_uint32
302 do_hostbase_nametype(OM_uint32 *minor, char *input, gss_name_t *output)
304 /* Get the nostname */
305 char *host = strchr(input, '@');
306 char netname[MAXNETNAMELEN+1];
309 /* If no host return bad name */
310 if (host == NULL)
311 return (GSS_S_BAD_NAME);
313 /* Advance pass the "@" sign */
314 host += 1;
316 /* Convert the hostname to its netname */
317 if (!host2netname(netname, host, NULL)) {
318 *minor = DH_NETNAME_FAILURE;
319 return (GSS_S_FAILURE);
322 /* Internalize the netname to output */
323 return (do_netname_nametype(minor, netname, output));
327 * do_exported_netname: Convert an exported Diffie-Hellman name
328 * to a Diffie-Hellman internal name.
330 static OM_uint32
331 do_exported_netname(dh_context_t ctx, /* Diffie-Hellman mech context */
332 OM_uint32 *minor, /* Mech status */
333 gss_buffer_t input, /* The export name to convert */
334 gss_name_t *output /* The converted internal name */)
336 /* All export names must start with this */
337 const char tokid[] = "\x04\x01";
338 const int tokid_len = 2;
339 const int OIDlen_len = 2;
340 const int namelen_len = 4;
341 unsigned char *p = (unsigned char *)input->value;
342 OM_uint32 len = input->length;
343 int mechoidlen;
344 OM_uint32 oidlen; /* includes object tag len & DER len bytes */
345 OM_uint32 namelen;
346 OM_uint32 currlen;
347 OM_uint32 bytes;
349 *minor = DH_BADARG_FAILURE;
351 /* The len must be at least this big */
352 if (len < tokid_len + OIDlen_len + namelen_len)
353 return (GSS_S_DEFECTIVE_TOKEN);
355 /* Export names must start with the token id of 0x04 0x01 */
356 if (memcmp(p, tokid, tokid_len) != 0)
357 return (GSS_S_DEFECTIVE_TOKEN);
358 p += tokid_len;
360 /* Decode the Mechanism oid */
361 oidlen = (*p++ << 8) & 0xff00;
362 oidlen |= *p++ & 0xff;
364 /* Check that we actually have the mechanism oid elements */
365 if (len < tokid_len + OIDlen_len + oidlen + namelen_len)
366 return (GSS_S_DEFECTIVE_TOKEN);
368 /* Compare that the input is for this mechanism */
369 if (*p++ != 0x06)
370 return (GSS_S_DEFECTIVE_TOKEN);
371 currlen = len - (tokid_len + OIDlen_len + oidlen + namelen_len);
372 if ((mechoidlen = get_der_length(&p, currlen, &bytes)) < 0)
373 return (GSS_S_DEFECTIVE_TOKEN);
374 if (mechoidlen != ctx->mech->length)
375 return (GSS_S_DEFECTIVE_TOKEN);
376 if (memcmp(p, ctx->mech->elements, mechoidlen) != 0)
377 return (GSS_S_DEFECTIVE_TOKEN);
378 p += mechoidlen;
380 /* Grab the length of the mechanism specific name per RFC 2078 */
381 namelen = (*p++ << 24) & 0xff000000;
382 namelen |= (*p++ << 16) & 0xff0000;
383 namelen |= (*p++ << 8) & 0xff00;
384 namelen |= *p++ & 0xff;
386 /* This should alway be false */
387 if (len < tokid_len + OIDlen_len + oidlen + namelen_len + namelen)
388 return (GSS_S_DEFECTIVE_TOKEN);
390 /* Make sure the bytes for the netname oid length are available */
391 if (namelen < OIDlen_len)
392 return (GSS_S_DEFECTIVE_TOKEN);
394 /* Get the netname oid length */
395 oidlen = (*p++ << 8) & 0xff00;
396 oidlen = *p++ & 0xff;
398 /* See if we have the elements of the netname oid */
399 if (namelen < OIDlen_len + oidlen)
400 return (GSS_S_DEFECTIVE_TOKEN);
402 /* Check that the oid is really a netname */
403 if (oidlen != __DH_GSS_C_NT_NETNAME->length)
404 return (GSS_S_DEFECTIVE_TOKEN);
405 if (memcmp(p, __DH_GSS_C_NT_NETNAME->elements,
406 __DH_GSS_C_NT_NETNAME->length) != 0)
407 return (GSS_S_DEFECTIVE_TOKEN);
409 /* p now points to the netname wich is null terminated */
410 p += oidlen;
413 * How the netname is encoded in an export name type for
414 * this mechanism. See _dh_gss_export_name below.
417 if (namelen != OIDlen_len + oidlen + strlen((char *)p) + 1)
418 return (GSS_S_DEFECTIVE_TOKEN);
420 /* Grab the netname */
421 *output = (gss_name_t)strdup((char *)p);
422 if (*output) {
423 *minor = 0;
424 return (GSS_S_COMPLETE);
427 *minor = DH_NOMEM_FAILURE;
428 return (GSS_S_FAILURE);
432 * __dh_gss_import_name: Diffie-Hellman entry point for gss_import_name.
433 * Given an input name of a specified name type, convert this to a
434 * Diffie-Hellman internal name (netname).
436 * The idea here is simply compare the name_type supplied with each
437 * name type that we know how to deal with. If we have a match we call
438 * the appropriate support routine form above. If we done't have a match
439 * we return GSS_S_BAD_NAMETYPE
441 OM_uint32
442 __dh_gss_import_name(void *ctx, /* Per mechanism context */
443 OM_uint32 *minor, /* Mechanism status */
444 gss_buffer_t input, /* The name to convert */
445 gss_OID name_type, /* of this name_type */
446 gss_name_t *output /* The converted name */)
448 char *name;
449 OM_uint32 stat;
451 if (minor == NULL || output == NULL)
452 return (GSS_S_CALL_INACCESSIBLE_WRITE);
454 if (input == NULL || input->value == NULL)
455 return (GSS_S_BAD_NAME | GSS_S_CALL_INACCESSIBLE_READ);
456 if (name_type == GSS_C_NO_OID)
457 return (GSS_S_BAD_NAMETYPE);
459 /* Set sane state */
460 *minor = DH_SUCCESS;
461 *output = GSS_C_NO_NAME;
463 /* UID in machine format */
464 if (__OID_equal(name_type, GSS_C_NT_MACHINE_UID_NAME)) {
465 uid_t uid;
466 if (input->length != sizeof (uid_t))
467 return (GSS_S_BAD_NAME);
468 uid = *(uid_t *)input->value;
469 /* Should we assume that the id is network byte order ??? */
470 /* uid = htonl(uid); No, this should be the local orfering */
471 return (do_uid_nametype(minor, uid, output));
473 /* Name that was exported with __dh_gss_export_name */
474 } else if (__OID_equal(name_type, GSS_C_NT_EXPORT_NAME)) {
475 stat = do_exported_netname((dh_context_t)ctx, minor,
476 input, output);
477 return (stat);
480 /* Null ternamte name so we can manipulate as a c-style string */
481 name = malloc(input->length+1);
482 if (name == NULL) {
483 *minor = DH_NOMEM_FAILURE;
484 return (GSS_S_FAILURE);
486 memcpy(name, input->value, input->length);
487 name[input->length] = '\0';
490 /* Diffie-Hellman (ONC RPC netname) */
491 if (__OID_equal(name_type, __DH_GSS_C_NT_NETNAME)) {
492 stat = do_netname_nametype(minor, name, output);
493 free(name);
494 return (stat);
495 /* Host based service name (service@hostname) */
496 } else if (__OID_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE)) {
497 stat = do_hostbase_nametype(minor, name, output);
498 free(name);
499 return (stat);
500 /* Thus local OS user name */
501 } else if (__OID_equal(name_type, GSS_C_NT_USER_NAME)) {
502 stat = do_username_nametype(minor, name, output);
503 free(name);
504 return (stat);
505 /* The os user id writen as a string */
506 } else if (__OID_equal(name_type, GSS_C_NT_STRING_UID_NAME)) {
507 char *p;
508 /* Convert the name to a uid */
509 uid_t uid = (uid_t)strtol(name, &p, 0);
510 free(name);
511 if (*p != '\0')
512 return (GSS_S_BAD_NAME);
513 return (do_uid_nametype(minor, uid, output));
514 } else {
515 /* Any thing else */
516 free(name);
517 return (GSS_S_BAD_NAMETYPE);
522 * __dh_gss_release_name: DH entry point for gss_release_name.
523 * Release an internal DH name.
525 OM_uint32
526 __dh_gss_release_name(void *ctx, OM_uint32 *minor, gss_name_t *name)
528 _NOTE(ARGUNUSED(ctx))
530 if (minor == 0 || name == 0)
531 return (GSS_S_CALL_INACCESSIBLE_WRITE);
533 *minor = DH_SUCCESS;
535 free(*name);
536 *name = GSS_C_NO_NAME;
538 return (GSS_S_COMPLETE);
541 /* Lock for initializing oid_name_tab */
542 static mutex_t name_tab_lock = DEFAULTMUTEX;
544 /* Table of name types that this mechanism understands */
545 static const gss_OID_desc * oid_name_tab[OID_MAX_NAME_ENTRIES];
548 * __dh_gss_inquire_names_for_mech: DH entry point for
549 * gss_inquire_names_for_mech.
551 * Return a set of OID name types that a mechanism can understand
553 OM_uint32
554 __dh_gss_inquire_names_for_mech(void *ctx, OM_uint32 *minor,
555 gss_OID mech, gss_OID_set *names)
557 _NOTE(ARGUNUSED(ctx,mech))
559 /* See if we need to initialize the table */
560 if (oid_name_tab[0] == 0) {
561 mutex_lock(&name_tab_lock);
562 /* If nobody sneaked in, initialize the table */
563 if (oid_name_tab[0] == 0) {
564 oid_name_tab[0] = __DH_GSS_C_NT_NETNAME;
565 oid_name_tab[1] = GSS_C_NT_HOSTBASED_SERVICE;
566 oid_name_tab[2] = GSS_C_NT_USER_NAME;
567 oid_name_tab[3] = GSS_C_NT_MACHINE_UID_NAME;
568 oid_name_tab[4] = GSS_C_NT_STRING_UID_NAME;
569 oid_name_tab[5] = GSS_C_NT_EXPORT_NAME;
570 /* oid_name_tab[6] = GSS_C_NT_ANONYMOUS_NAME; */
572 mutex_unlock(&name_tab_lock);
575 /* Return the set of OIDS from the table */
576 if ((*minor = __OID_copy_set_from_array(names,
577 oid_name_tab, 6)) != DH_SUCCESS)
578 return (GSS_S_FAILURE);
580 return (GSS_S_COMPLETE);
585 * Private libgss entry point to convert a principal name to uid.
587 OM_uint32
588 __dh_pname_to_uid(void *ctx, /* DH mech context (not used) */
589 OM_uint32 *minor, /* Mech status */
590 const gss_name_t pname, /* principal */
591 uid_t *uid /* where to put the uid */)
593 _NOTE(ARGUNUSED(ctx))
595 gid_t gid;
596 gid_t glist[NGRPS];
597 int glen;
598 /* Convert the principal name to a netname */
599 char *netname = (char *)pname;
600 char host_netname[MAXNETNAMELEN+1];
602 if (pname == 0)
603 return (GSS_S_BAD_NAME | GSS_S_CALL_INACCESSIBLE_READ);
604 if (minor == 0 || uid == 0)
605 return (GSS_S_CALL_INACCESSIBLE_WRITE);
607 *minor = DH_SUCCESS;
608 *uid = UID_NOBODY;
610 /* First try to convert as a user */
611 if (netname2user(netname, uid, &gid, &glen, glist))
612 return (GSS_S_COMPLETE);
613 /* Get this hosts netname */
614 else if (host2netname(host_netname, NULL, NULL)) {
616 * If the netname is this host's netname then we're root
617 * else we're nobody.
619 if (strncmp(netname, host_netname, MAXNETNAMELEN) == 0)
620 *uid = 0;
621 return (GSS_S_COMPLETE);
624 /* We could not get a netname */
625 *minor = DH_NETNAME_FAILURE;
626 return (GSS_S_FAILURE);
630 * __dh_gss_export_name: Diffie-Hellman support for gss_export_name.
631 * Given a Diffie-Hellman internal name return the GSS exported format.
633 OM_uint32
634 __dh_gss_export_name(void *ctx, /* Per mechanism context */
635 OM_uint32 *minor, /* Mechanism status */
636 const gss_name_t input_name, /* The name to export */
637 gss_buffer_t exported_name /* Exported name goes here */)
639 /* input_name is dh principal name */
640 dh_principal pname = (dh_principal)input_name;
641 dh_context_t dc = (dh_context_t)ctx;
642 /* Magic for exported blobs */
643 const char tokid[] = "\x04\x01";
644 const int tokid_len = 2;
645 const int OIDlen_len = 2; /* Why did they do this? */
646 const int namelen_len = 4;
647 const int mechoid_tag_len = 1;
648 unsigned char *p;
649 OM_uint32 len;
650 OM_uint32 namelen;
651 OM_uint32 currlen;
652 OM_uint32 oid_der_len = 0;
654 if (minor == 0 || exported_name == GSS_C_NO_BUFFER)
655 return (GSS_S_CALL_INACCESSIBLE_WRITE);
656 if (input_name == GSS_C_NO_NAME)
657 return (GSS_S_CALL_INACCESSIBLE_READ);
659 /* Set sane outputs */
660 *minor = DH_SUCCESS;
661 exported_name->length = 0;
662 exported_name->value = NULL;
664 /* Determine the length of the name */
665 namelen = OIDlen_len + __DH_GSS_C_NT_NETNAME->length
666 + strlen(pname)+1;
667 oid_der_len = der_length_size(dc->mech->length);
668 /* Find the total length */
669 len = tokid_len + OIDlen_len + mechoid_tag_len + oid_der_len
670 + dc->mech->length + namelen_len + namelen;
672 /* Allocate the blob */
673 p = New(unsigned char, len);
674 if (p == NULL) {
675 *minor = DH_NOMEM_FAILURE;
676 return (GSS_S_FAILURE);
678 /* Set the blob to the exported name */
679 exported_name->length = len;
680 exported_name->value = p;
682 /* Start with some magic */
683 memcpy(p, tokid, tokid_len);
684 p += tokid_len;
687 * The spec only allows two bytes for the oid length.
688 * We are assuming here that the correct encodeing is MSB first as
689 * was done in libgss.
692 *p++ = ((mechoid_tag_len + oid_der_len + dc->mech->length)
693 & 0xff00) >> 8;
694 *p++ = ((mechoid_tag_len + oid_der_len + dc->mech->length)
695 & 0x00ff);
697 /* Now the mechanism OID DER Encoding */
698 *p++ = 0x06; /* Universal Tag for OID */
699 currlen = len - tokid_len - OIDlen_len - mechoid_tag_len;
700 if (!put_der_length(dc->mech->length, &p, currlen) == 0) {
701 return (GSS_S_FAILURE);
704 /* Now the mechanism OID elements */
705 memcpy(p, dc->mech->elements, dc->mech->length);
706 p += dc->mech->length;
708 /* The name length most MSB first */
709 *p++ = (namelen & 0xff000000) >> 24;
710 *p++ = (namelen & 0x00ff0000) >> 16;
711 *p++ = (namelen & 0x0000ff00) >> 8;
712 *p++ = (namelen & 0x000000ff);
715 * We'll now encode the netname oid. Again we'll just use 2 bytes.
716 * This is the same encoding that the libgss implementor uses, so
717 * we'll just follow along.
720 *p++ = (__DH_GSS_C_NT_NETNAME->length & 0xff00) >> 8;
721 *p++ = (__DH_GSS_C_NT_NETNAME->length &0x00ff);
723 /* The netname oid values */
724 memcpy(p, __DH_GSS_C_NT_NETNAME->elements,
725 __DH_GSS_C_NT_NETNAME->length);
727 p += __DH_GSS_C_NT_NETNAME->length;
729 /* Now we copy the netname including the null byte to be safe */
730 memcpy(p, pname, strlen(pname) + 1);
732 return (GSS_S_COMPLETE);
736 * Support routine for __dh_internal_release_oid. Return True if
737 * the supplied OID points to the reference OID or if the elements
738 * of the reference OID are the same as the supplied OID. In the
739 * latter case, just free the OID container and set the pointer to it
740 * to GSS_C_NO_OID. Otherwise return false
742 static int
743 release_oid(const gss_OID_desc * const ref, gss_OID *oid)
745 gss_OID id = *oid;
747 if (id == ref)
748 return (TRUE);
751 * If some on create a shallow copy free, the structure point to
752 * id and set the pointer to it to GSS_C_NO_OID
754 if (id->elements == ref->elements) {
755 Free(id);
756 *oid = GSS_C_NO_OID;
757 return (TRUE);
760 return (FALSE);
764 * __dh_gss_internal_release_oid: DH support for the gss_internal_relaese_oid
765 * entry. Check that the refence to an oid is one of our mechanisms static
766 * OIDS. If it is return true indicating to libgss that we have handled the
767 * release of that OID. Otherwise we return false and let libgss deal with it.
769 * The only OIDS we know are the calling mechanism found in the context
770 * and the shared DH_GSS_C_NT_NETNAME name type
772 OM_uint32
773 __dh_gss_internal_release_oid(void *ctx, OM_uint32 *minor, gss_OID *oid)
775 dh_context_t dhcxt = (dh_context_t)ctx;
777 if (minor == 0)
778 return (GSS_S_CALL_INACCESSIBLE_WRITE);
780 *minor = DH_SUCCESS;
782 if (oid == NULL || *oid == NULL)
783 return (GSS_S_COMPLETE);
785 if (release_oid(dhcxt->mech, oid))
786 return (GSS_S_COMPLETE);
788 if (release_oid(__DH_GSS_C_NT_NETNAME, oid))
789 return (GSS_S_COMPLETE);
791 return (GSS_S_FAILURE);