10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*5053Sgtb * Common Development and Distribution License (the "License"). 6*5053Sgtb * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*5053Sgtb * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <mechglueP.h> 290Sstevel@tonic-gate #include <stdio.h> 300Sstevel@tonic-gate #include <stdlib.h> 310Sstevel@tonic-gate #include <strings.h> 320Sstevel@tonic-gate #include <errno.h> 330Sstevel@tonic-gate 340Sstevel@tonic-gate #define MSO_BIT (8*(sizeof (int) - 1)) /* Most significant octet bit */ 350Sstevel@tonic-gate 360Sstevel@tonic-gate /* 370Sstevel@tonic-gate * This file contains the support routines for the glue layer. 380Sstevel@tonic-gate */ 390Sstevel@tonic-gate 400Sstevel@tonic-gate /* 410Sstevel@tonic-gate * get_der_length: Givin a pointer to a buffer that contains a DER encoded 420Sstevel@tonic-gate * length, decode the length updating the buffer to point to the character 430Sstevel@tonic-gate * after the DER encoding. The parameter bytes will point to the number of 440Sstevel@tonic-gate * bytes that made up the DER encoding of the length originally pointed to 450Sstevel@tonic-gate * by the buffer. Note we return -1 on error. 460Sstevel@tonic-gate */ 470Sstevel@tonic-gate int 480Sstevel@tonic-gate get_der_length(unsigned char **buf, unsigned int buf_len, unsigned int *bytes) 490Sstevel@tonic-gate { 500Sstevel@tonic-gate /* p points to the beginning of the buffer */ 510Sstevel@tonic-gate unsigned char *p = *buf; 520Sstevel@tonic-gate int length, new_length; 530Sstevel@tonic-gate int octets; 540Sstevel@tonic-gate 550Sstevel@tonic-gate if (buf_len < 1) 560Sstevel@tonic-gate return (-1); 570Sstevel@tonic-gate 580Sstevel@tonic-gate /* We should have at least one byte */ 590Sstevel@tonic-gate *bytes = 1; 600Sstevel@tonic-gate 610Sstevel@tonic-gate /* 620Sstevel@tonic-gate * If the High order bit is not set then the length is just the value 630Sstevel@tonic-gate * of *p. 640Sstevel@tonic-gate */ 650Sstevel@tonic-gate if (*p < 128) { 660Sstevel@tonic-gate *buf = p+1; /* Advance the buffer */ 670Sstevel@tonic-gate return (*p); /* return the length */ 680Sstevel@tonic-gate } 690Sstevel@tonic-gate 700Sstevel@tonic-gate /* 710Sstevel@tonic-gate * if the High order bit is set, then the low order bits represent 720Sstevel@tonic-gate * the number of bytes that contain the DER encoding of the length. 730Sstevel@tonic-gate */ 740Sstevel@tonic-gate 750Sstevel@tonic-gate octets = *p++ & 0x7f; 760Sstevel@tonic-gate *bytes += octets; 770Sstevel@tonic-gate 780Sstevel@tonic-gate /* See if the supplied buffer contains enough bytes for the length. */ 790Sstevel@tonic-gate if (octets > buf_len - 1) 800Sstevel@tonic-gate return (-1); 810Sstevel@tonic-gate 820Sstevel@tonic-gate /* 830Sstevel@tonic-gate * Calculate a multibyte length. The length is encoded as an 840Sstevel@tonic-gate * unsigned integer base 256. 850Sstevel@tonic-gate */ 860Sstevel@tonic-gate for (length = 0; octets; octets--) { 870Sstevel@tonic-gate new_length = (length << 8) + *p++; 880Sstevel@tonic-gate if (new_length < length) /* overflow */ 890Sstevel@tonic-gate return (-1); 900Sstevel@tonic-gate length = new_length; 910Sstevel@tonic-gate } 920Sstevel@tonic-gate 930Sstevel@tonic-gate *buf = p; /* Advance the buffer */ 940Sstevel@tonic-gate 950Sstevel@tonic-gate return (length); 960Sstevel@tonic-gate } 970Sstevel@tonic-gate 980Sstevel@tonic-gate /* 990Sstevel@tonic-gate * der_length_size: Return the number of bytes to encode a given length. 1000Sstevel@tonic-gate */ 1010Sstevel@tonic-gate unsigned int 1020Sstevel@tonic-gate der_length_size(unsigned int len) 1030Sstevel@tonic-gate { 1040Sstevel@tonic-gate int i; 1050Sstevel@tonic-gate 1060Sstevel@tonic-gate if (len < 128) 1070Sstevel@tonic-gate return (1); 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate for (i = 0; len; i++) { 1100Sstevel@tonic-gate len >>= 8; 1110Sstevel@tonic-gate } 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate return (i+1); 1140Sstevel@tonic-gate } 1150Sstevel@tonic-gate 1160Sstevel@tonic-gate /* 1170Sstevel@tonic-gate * put_der_length: Encode the supplied length into the buffer pointed to 1180Sstevel@tonic-gate * by buf. max_length represents the maximum length of the buffer pointed 1190Sstevel@tonic-gate * to by buff. We will advance buf to point to the character after the newly 1200Sstevel@tonic-gate * DER encoded length. We return 0 on success or -l it the length cannot 1210Sstevel@tonic-gate * be encoded in max_len characters. 1220Sstevel@tonic-gate */ 1230Sstevel@tonic-gate int 1240Sstevel@tonic-gate put_der_length(unsigned length, unsigned char **buf, unsigned int max_len) 1250Sstevel@tonic-gate { 1260Sstevel@tonic-gate unsigned char *s = *buf, *p; 1270Sstevel@tonic-gate unsigned int buf_len = 0; 1280Sstevel@tonic-gate int i, first; 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate /* Oops */ 1310Sstevel@tonic-gate if (buf == 0 || max_len < 1) 1320Sstevel@tonic-gate return (-1); 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate /* Single byte is the length */ 1350Sstevel@tonic-gate if (length < 128) { 1360Sstevel@tonic-gate *s++ = length; 1370Sstevel@tonic-gate *buf = s; 1380Sstevel@tonic-gate return (0); 1390Sstevel@tonic-gate } 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate /* First byte contains the number of octets */ 1420Sstevel@tonic-gate p = s + 1; 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate /* Running total of the DER encoding length */ 1450Sstevel@tonic-gate buf_len = 0; 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate /* 1480Sstevel@tonic-gate * Encode MSB first. We do the encoding by setting a shift 1490Sstevel@tonic-gate * factor to MSO_BIT (24 for 32 bit words) and then shifting the length 1500Sstevel@tonic-gate * by the factor. We then encode the resulting low order byte. 1510Sstevel@tonic-gate * We subtract 8 from the shift factor and repeat to ecnode the next 1520Sstevel@tonic-gate * byte. We stop when the shift factor is zero or we've run out of 1530Sstevel@tonic-gate * buffer to encode into. 1540Sstevel@tonic-gate */ 1550Sstevel@tonic-gate first = 0; 1560Sstevel@tonic-gate for (i = MSO_BIT; i >= 0 && buf_len <= max_len; i -= 8) { 1570Sstevel@tonic-gate unsigned int v; 1580Sstevel@tonic-gate v = (length >> i) & 0xff; 1590Sstevel@tonic-gate if ((v) || first) { 1600Sstevel@tonic-gate buf_len += 1; 1610Sstevel@tonic-gate *p++ = v; 1620Sstevel@tonic-gate first = 1; 1630Sstevel@tonic-gate } 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate if (i >= 0) /* buffer overflow */ 1660Sstevel@tonic-gate return (-1); 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate /* 1690Sstevel@tonic-gate * We go back now and set the first byte to be the length with 1700Sstevel@tonic-gate * the high order bit set. 1710Sstevel@tonic-gate */ 1720Sstevel@tonic-gate *s = buf_len | 0x80; 1730Sstevel@tonic-gate *buf = p; 1740Sstevel@tonic-gate 1750Sstevel@tonic-gate return (0); 1760Sstevel@tonic-gate } 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate /* 1800Sstevel@tonic-gate * glue routine for get_mech_type 1810Sstevel@tonic-gate * 1820Sstevel@tonic-gate */ 1830Sstevel@tonic-gate OM_uint32 1840Sstevel@tonic-gate __gss_get_mech_type(OID, token) 1850Sstevel@tonic-gate gss_OID OID; 1860Sstevel@tonic-gate const gss_buffer_t token; 1870Sstevel@tonic-gate { 1880Sstevel@tonic-gate unsigned char *buffer_ptr; 1890Sstevel@tonic-gate int length; 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate /* 1920Sstevel@tonic-gate * This routine reads the prefix of "token" in order to determine 1930Sstevel@tonic-gate * its mechanism type. It assumes the encoding suggested in 1940Sstevel@tonic-gate * Appendix B of RFC 1508. This format starts out as follows : 1950Sstevel@tonic-gate * 1960Sstevel@tonic-gate * tag for APPLICATION 0, Sequence[constructed, definite length] 1970Sstevel@tonic-gate * length of remainder of token 1980Sstevel@tonic-gate * tag of OBJECT IDENTIFIER 1990Sstevel@tonic-gate * length of mechanism OID 2000Sstevel@tonic-gate * encoding of mechanism OID 2010Sstevel@tonic-gate * <the rest of the token> 2020Sstevel@tonic-gate * 2030Sstevel@tonic-gate * Numerically, this looks like : 2040Sstevel@tonic-gate * 2050Sstevel@tonic-gate * 0x60 2060Sstevel@tonic-gate * <length> - could be multiple bytes 2070Sstevel@tonic-gate * 0x06 2080Sstevel@tonic-gate * <length> - assume only one byte, hence OID length < 127 2090Sstevel@tonic-gate * <mech OID bytes> 2100Sstevel@tonic-gate * 2110Sstevel@tonic-gate * The routine fills in the OID value and returns an error as necessary. 2120Sstevel@tonic-gate */ 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate if (OID == NULL) 2150Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate if ((token == NULL) || (token->value == NULL)) 2180Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN); 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate /* Skip past the APP/Sequnce byte and the token length */ 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate buffer_ptr = (unsigned char *) token->value; 2230Sstevel@tonic-gate 2240Sstevel@tonic-gate if (*(buffer_ptr++) != 0x60) 2250Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN); 2260Sstevel@tonic-gate length = *buffer_ptr++; 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate /* check if token length is null */ 2290Sstevel@tonic-gate if (length == 0) 2300Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN); 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate if (length & 0x80) { 2330Sstevel@tonic-gate if ((length & 0x7f) > 4) 2340Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN); 2350Sstevel@tonic-gate buffer_ptr += length & 0x7f; 2360Sstevel@tonic-gate } 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate if (*(buffer_ptr++) != 0x06) 2390Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN); 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate OID->length = (OM_uint32) *(buffer_ptr++); 2420Sstevel@tonic-gate OID->elements = (void *) buffer_ptr; 2430Sstevel@tonic-gate return (GSS_S_COMPLETE); 2440Sstevel@tonic-gate } 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate /* 2480Sstevel@tonic-gate * Internal routines to get and release an internal mechanism name 2490Sstevel@tonic-gate */ 2500Sstevel@tonic-gate OM_uint32 __gss_import_internal_name(minor_status, mech_type, union_name, 2510Sstevel@tonic-gate internal_name) 2520Sstevel@tonic-gate OM_uint32 *minor_status; 2530Sstevel@tonic-gate const gss_OID mech_type; 2540Sstevel@tonic-gate gss_union_name_t union_name; 2550Sstevel@tonic-gate gss_name_t *internal_name; 2560Sstevel@tonic-gate { 2570Sstevel@tonic-gate OM_uint32 status; 2580Sstevel@tonic-gate gss_mechanism mech; 2590Sstevel@tonic-gate 2600Sstevel@tonic-gate mech = __gss_get_mechanism(mech_type); 2610Sstevel@tonic-gate if (mech) { 2620Sstevel@tonic-gate if (mech->gss_import_name) 2630Sstevel@tonic-gate status = mech->gss_import_name( 2640Sstevel@tonic-gate mech->context, 2650Sstevel@tonic-gate minor_status, 2660Sstevel@tonic-gate union_name->external_name, 2670Sstevel@tonic-gate union_name->name_type, 2680Sstevel@tonic-gate internal_name); 2690Sstevel@tonic-gate else 2700Sstevel@tonic-gate status = GSS_S_UNAVAILABLE; 2710Sstevel@tonic-gate 2720Sstevel@tonic-gate return (status); 2730Sstevel@tonic-gate } 2740Sstevel@tonic-gate 2750Sstevel@tonic-gate return (GSS_S_BAD_MECH); 2760Sstevel@tonic-gate } 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate OM_uint32 __gss_export_internal_name(minor_status, mech_type, 2800Sstevel@tonic-gate internal_name, name_buf) 2810Sstevel@tonic-gate OM_uint32 *minor_status; 2820Sstevel@tonic-gate const gss_OID mech_type; 2830Sstevel@tonic-gate const gss_name_t internal_name; 2840Sstevel@tonic-gate gss_buffer_t name_buf; 2850Sstevel@tonic-gate { 2860Sstevel@tonic-gate OM_uint32 status; 2870Sstevel@tonic-gate gss_mechanism mech; 2880Sstevel@tonic-gate gss_buffer_desc dispName; 2890Sstevel@tonic-gate gss_OID nameOid; 2900Sstevel@tonic-gate unsigned char *buf = NULL; 2910Sstevel@tonic-gate const unsigned char tokId[] = "\x04\x01"; 2920Sstevel@tonic-gate const int tokIdLen = 2; 2930Sstevel@tonic-gate const int mechOidLenLen = 2, mechOidTagLen = 1, nameLenLen = 4; 2940Sstevel@tonic-gate int mechOidDERLen = 0; 2950Sstevel@tonic-gate int mechOidLen = 0; 2960Sstevel@tonic-gate 2970Sstevel@tonic-gate mech = __gss_get_mechanism(mech_type); 2980Sstevel@tonic-gate if (!mech) 2990Sstevel@tonic-gate return (GSS_S_BAD_MECH); 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate if (mech->gss_export_name) 3020Sstevel@tonic-gate return (mech->gss_export_name(mech->context, 3030Sstevel@tonic-gate minor_status, 3040Sstevel@tonic-gate internal_name, 3050Sstevel@tonic-gate name_buf)); 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate /* 3080Sstevel@tonic-gate * if we are here it is because the mechanism does not provide 3090Sstevel@tonic-gate * a gss_export_name so we will use our implementation. We 3100Sstevel@tonic-gate * do required that the mechanism define a gss_display_name. 3110Sstevel@tonic-gate */ 3120Sstevel@tonic-gate if (!mech->gss_display_name) 3130Sstevel@tonic-gate return (GSS_S_UNAVAILABLE); 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate /* 3160Sstevel@tonic-gate * NOTE: RFC2743 (section 3.2) governs the format of the outer 3170Sstevel@tonic-gate * wrapper of exported names; the mechanisms' specs govern 3180Sstevel@tonic-gate * the format of the inner portion of the exported name 3190Sstevel@tonic-gate * and, for some (e.g., RFC1964, the Kerberos V mech), a 3200Sstevel@tonic-gate * generic default as implemented here will do. 3210Sstevel@tonic-gate * 3220Sstevel@tonic-gate * The outer wrapper of an exported MN is: 2-octet tok Id 3230Sstevel@tonic-gate * (0x0401) + 2-octet network-byte order mech OID length + mech 3240Sstevel@tonic-gate * oid (in DER format, including DER tag and DER length) + 3250Sstevel@tonic-gate * 4-octet network-byte order length of inner portion + inner 3260Sstevel@tonic-gate * portion. 3270Sstevel@tonic-gate * 3280Sstevel@tonic-gate * For the Kerberos V mechanism the inner portion of an exported 3290Sstevel@tonic-gate * MN is the display name string and ignores the name type OID 3300Sstevel@tonic-gate * altogether. And we hope this will be so for any future 3310Sstevel@tonic-gate * mechanisms also, so that factoring name export/import out of 3320Sstevel@tonic-gate * the mech and into libgss pays off. 3330Sstevel@tonic-gate */ 3340Sstevel@tonic-gate if ((status = mech->gss_display_name(mech->context, 3350Sstevel@tonic-gate minor_status, 3360Sstevel@tonic-gate internal_name, 3370Sstevel@tonic-gate &dispName, 3380Sstevel@tonic-gate &nameOid)) 3390Sstevel@tonic-gate != GSS_S_COMPLETE) 3400Sstevel@tonic-gate return (status); 3410Sstevel@tonic-gate 3420Sstevel@tonic-gate /* determine the size of the buffer needed */ 3430Sstevel@tonic-gate mechOidDERLen = der_length_size(mech_type->length); 3440Sstevel@tonic-gate name_buf->length = tokIdLen + mechOidLenLen + 3450Sstevel@tonic-gate mechOidTagLen + mechOidDERLen + 3460Sstevel@tonic-gate mech_type->length + 3470Sstevel@tonic-gate nameLenLen + dispName.length; 3480Sstevel@tonic-gate if ((name_buf->value = (void*)malloc(name_buf->length)) == 3490Sstevel@tonic-gate (void*)NULL) { 3500Sstevel@tonic-gate name_buf->length = 0; 3510Sstevel@tonic-gate (void) gss_release_buffer(&status, &dispName); 3520Sstevel@tonic-gate return (GSS_S_FAILURE); 3530Sstevel@tonic-gate } 3540Sstevel@tonic-gate 3550Sstevel@tonic-gate /* now create the name ..... */ 3560Sstevel@tonic-gate buf = (unsigned char *)name_buf->value; 3570Sstevel@tonic-gate (void) memset(name_buf->value, 0, name_buf->length); 3580Sstevel@tonic-gate (void) memcpy(buf, tokId, tokIdLen); 3590Sstevel@tonic-gate buf += tokIdLen; 3600Sstevel@tonic-gate 3610Sstevel@tonic-gate /* spec allows only 2 bytes for the mech oid length */ 3620Sstevel@tonic-gate mechOidLen = mechOidDERLen + mechOidTagLen + mech_type->length; 3630Sstevel@tonic-gate *buf++ = (mechOidLen & 0xFF00) >> 8; 3640Sstevel@tonic-gate *buf++ = (mechOidLen & 0x00FF); 3650Sstevel@tonic-gate 3660Sstevel@tonic-gate /* 3670Sstevel@tonic-gate * DER Encoding of mech OID contains OID Tag (0x06), length and 3680Sstevel@tonic-gate * mech OID value 3690Sstevel@tonic-gate */ 3700Sstevel@tonic-gate *buf++ = 0x06; 3710Sstevel@tonic-gate if (put_der_length(mech_type->length, &buf, 3720Sstevel@tonic-gate (name_buf->length - tokIdLen -2)) != 0) { 3730Sstevel@tonic-gate name_buf->length = 0; 3740Sstevel@tonic-gate free(name_buf->value); 3750Sstevel@tonic-gate (void) gss_release_buffer(&status, &dispName); 3760Sstevel@tonic-gate return (GSS_S_FAILURE); 3770Sstevel@tonic-gate } 3780Sstevel@tonic-gate 3790Sstevel@tonic-gate (void) memcpy(buf, mech_type->elements, mech_type->length); 3800Sstevel@tonic-gate buf += mech_type->length; 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate /* spec designates the next 4 bytes for the name length */ 3830Sstevel@tonic-gate *buf++ = (dispName.length & 0xFF000000) >> 24; 3840Sstevel@tonic-gate *buf++ = (dispName.length & 0x00FF0000) >> 16; 3850Sstevel@tonic-gate *buf++ = (dispName.length & 0x0000FF00) >> 8; 3860Sstevel@tonic-gate *buf++ = (dispName.length & 0X000000FF); 3870Sstevel@tonic-gate 3880Sstevel@tonic-gate /* for the final ingredient - add the name from gss_display_name */ 3890Sstevel@tonic-gate (void) memcpy(buf, dispName.value, dispName.length); 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate /* release the buffer obtained from gss_display_name */ 3920Sstevel@tonic-gate (void) gss_release_buffer(minor_status, &dispName); 3930Sstevel@tonic-gate return (GSS_S_COMPLETE); 3940Sstevel@tonic-gate } /* __gss_export_internal_name */ 3950Sstevel@tonic-gate 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate OM_uint32 __gss_display_internal_name(minor_status, mech_type, internal_name, 3980Sstevel@tonic-gate external_name, name_type) 3990Sstevel@tonic-gate OM_uint32 *minor_status; 4000Sstevel@tonic-gate const gss_OID mech_type; 4010Sstevel@tonic-gate const gss_name_t internal_name; 4020Sstevel@tonic-gate gss_buffer_t external_name; 4030Sstevel@tonic-gate gss_OID *name_type; 4040Sstevel@tonic-gate { 4050Sstevel@tonic-gate OM_uint32 status; 4060Sstevel@tonic-gate gss_mechanism mech; 4070Sstevel@tonic-gate 4080Sstevel@tonic-gate mech = __gss_get_mechanism(mech_type); 4090Sstevel@tonic-gate if (mech) { 4100Sstevel@tonic-gate if (mech->gss_display_name) 4110Sstevel@tonic-gate status = mech->gss_display_name( 4120Sstevel@tonic-gate mech->context, 4130Sstevel@tonic-gate minor_status, 4140Sstevel@tonic-gate internal_name, 4150Sstevel@tonic-gate external_name, 4160Sstevel@tonic-gate name_type); 4170Sstevel@tonic-gate else 4180Sstevel@tonic-gate status = GSS_S_UNAVAILABLE; 4190Sstevel@tonic-gate 4200Sstevel@tonic-gate return (status); 4210Sstevel@tonic-gate } 4220Sstevel@tonic-gate 4230Sstevel@tonic-gate return (GSS_S_BAD_MECH); 4240Sstevel@tonic-gate } 4250Sstevel@tonic-gate 4260Sstevel@tonic-gate OM_uint32 4270Sstevel@tonic-gate __gss_release_internal_name(minor_status, mech_type, internal_name) 4280Sstevel@tonic-gate OM_uint32 *minor_status; 4290Sstevel@tonic-gate const gss_OID mech_type; 4300Sstevel@tonic-gate gss_name_t *internal_name; 4310Sstevel@tonic-gate { 4320Sstevel@tonic-gate OM_uint32 status; 4330Sstevel@tonic-gate gss_mechanism mech; 4340Sstevel@tonic-gate 4350Sstevel@tonic-gate mech = __gss_get_mechanism(mech_type); 4360Sstevel@tonic-gate if (mech) { 4370Sstevel@tonic-gate if (mech->gss_release_name) 4380Sstevel@tonic-gate status = mech->gss_release_name( 4390Sstevel@tonic-gate mech->context, 4400Sstevel@tonic-gate minor_status, 4410Sstevel@tonic-gate internal_name); 4420Sstevel@tonic-gate else 4430Sstevel@tonic-gate status = GSS_S_UNAVAILABLE; 4440Sstevel@tonic-gate 4450Sstevel@tonic-gate return (status); 4460Sstevel@tonic-gate } 4470Sstevel@tonic-gate 4480Sstevel@tonic-gate return (GSS_S_BAD_MECH); 4490Sstevel@tonic-gate } 4500Sstevel@tonic-gate 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate /* 4530Sstevel@tonic-gate * This function converts an internal gssapi name to a union gssapi 4540Sstevel@tonic-gate * name. Note that internal_name should be considered "consumed" by 4550Sstevel@tonic-gate * this call, whether or not we return an error. 4560Sstevel@tonic-gate */ 4570Sstevel@tonic-gate OM_uint32 __gss_convert_name_to_union_name(minor_status, mech, 4580Sstevel@tonic-gate internal_name, external_name) 4590Sstevel@tonic-gate OM_uint32 *minor_status; 4600Sstevel@tonic-gate gss_mechanism mech; 4610Sstevel@tonic-gate gss_name_t internal_name; 4620Sstevel@tonic-gate gss_name_t *external_name; 4630Sstevel@tonic-gate { 4640Sstevel@tonic-gate OM_uint32 major_status, tmp; 4650Sstevel@tonic-gate gss_union_name_t union_name; 4660Sstevel@tonic-gate 4670Sstevel@tonic-gate union_name = (gss_union_name_t)malloc(sizeof (gss_union_name_desc)); 4680Sstevel@tonic-gate if (!union_name) { 4690Sstevel@tonic-gate goto allocation_failure; 4700Sstevel@tonic-gate } 4710Sstevel@tonic-gate union_name->mech_type = 0; 4720Sstevel@tonic-gate union_name->mech_name = internal_name; 4730Sstevel@tonic-gate union_name->name_type = 0; 4740Sstevel@tonic-gate union_name->external_name = 0; 4750Sstevel@tonic-gate 4760Sstevel@tonic-gate major_status = generic_gss_copy_oid(minor_status, &mech->mech_type, 4770Sstevel@tonic-gate &union_name->mech_type); 4780Sstevel@tonic-gate if (major_status != GSS_S_COMPLETE) 4790Sstevel@tonic-gate goto allocation_failure; 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate union_name->external_name = 4820Sstevel@tonic-gate (gss_buffer_t)malloc(sizeof (gss_buffer_desc)); 4830Sstevel@tonic-gate if (!union_name->external_name) { 4840Sstevel@tonic-gate goto allocation_failure; 4850Sstevel@tonic-gate } 4860Sstevel@tonic-gate 4870Sstevel@tonic-gate major_status = mech->gss_display_name(mech->context, minor_status, 4880Sstevel@tonic-gate internal_name, 4890Sstevel@tonic-gate union_name->external_name, 4900Sstevel@tonic-gate &union_name->name_type); 4910Sstevel@tonic-gate if (major_status != GSS_S_COMPLETE) 4920Sstevel@tonic-gate goto allocation_failure; 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate *external_name = (gss_name_t)union_name; 4950Sstevel@tonic-gate return (GSS_S_COMPLETE); 4960Sstevel@tonic-gate 4970Sstevel@tonic-gate allocation_failure: 4980Sstevel@tonic-gate if (union_name) { 4990Sstevel@tonic-gate if (union_name->external_name) { 5000Sstevel@tonic-gate if (union_name->external_name->value) 5010Sstevel@tonic-gate free(union_name->external_name->value); 5020Sstevel@tonic-gate free(union_name->external_name); 5030Sstevel@tonic-gate } 5040Sstevel@tonic-gate if (union_name->name_type) 5050Sstevel@tonic-gate (void) gss_release_oid(&tmp, &union_name->name_type); 5060Sstevel@tonic-gate if (union_name->mech_type) 5070Sstevel@tonic-gate (void) gss_release_oid(&tmp, &union_name->mech_type); 5080Sstevel@tonic-gate free(union_name); 5090Sstevel@tonic-gate } 5100Sstevel@tonic-gate /* 5110Sstevel@tonic-gate * do as the top comment says - since we are now owners of 5120Sstevel@tonic-gate * internal_name, we must clean it up 5130Sstevel@tonic-gate */ 5140Sstevel@tonic-gate if (internal_name) 5150Sstevel@tonic-gate (void) __gss_release_internal_name(&tmp, &mech->mech_type, 5160Sstevel@tonic-gate &internal_name); 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate return (major_status); 5190Sstevel@tonic-gate } 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate /* 5220Sstevel@tonic-gate * Glue routine for returning the mechanism-specific credential from a 5230Sstevel@tonic-gate * external union credential. 5240Sstevel@tonic-gate */ 5250Sstevel@tonic-gate gss_cred_id_t 5260Sstevel@tonic-gate __gss_get_mechanism_cred(union_cred, mech_type) 5270Sstevel@tonic-gate const gss_union_cred_t union_cred; 5280Sstevel@tonic-gate const gss_OID mech_type; 5290Sstevel@tonic-gate { 5300Sstevel@tonic-gate int i; 5310Sstevel@tonic-gate 5320Sstevel@tonic-gate if (union_cred == (gss_union_cred_t)GSS_C_NO_CREDENTIAL) 5330Sstevel@tonic-gate return (GSS_C_NO_CREDENTIAL); 5340Sstevel@tonic-gate 5350Sstevel@tonic-gate for (i = 0; i < union_cred->count; i++) { 5360Sstevel@tonic-gate if (g_OID_equal(mech_type, &union_cred->mechs_array[i])) 5370Sstevel@tonic-gate return (union_cred->cred_array[i]); 5380Sstevel@tonic-gate } 5390Sstevel@tonic-gate return (GSS_C_NO_CREDENTIAL); 5400Sstevel@tonic-gate } 5410Sstevel@tonic-gate 5420Sstevel@tonic-gate 5430Sstevel@tonic-gate /* 5440Sstevel@tonic-gate * Routine to create and copy the gss_buffer_desc structure. 5450Sstevel@tonic-gate * Both space for the structure and the data is allocated. 5460Sstevel@tonic-gate */ 5470Sstevel@tonic-gate OM_uint32 548*5053Sgtb gssint_create_copy_buffer(srcBuf, destBuf, addNullChar) 5490Sstevel@tonic-gate const gss_buffer_t srcBuf; 5500Sstevel@tonic-gate gss_buffer_t *destBuf; 5510Sstevel@tonic-gate int addNullChar; 5520Sstevel@tonic-gate { 5530Sstevel@tonic-gate gss_buffer_t aBuf; 5540Sstevel@tonic-gate int len; 5550Sstevel@tonic-gate 5560Sstevel@tonic-gate if (destBuf == NULL) 5570Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 5580Sstevel@tonic-gate 5590Sstevel@tonic-gate *destBuf = 0; 5600Sstevel@tonic-gate 5610Sstevel@tonic-gate aBuf = (gss_buffer_t)malloc(sizeof (gss_buffer_desc)); 5620Sstevel@tonic-gate if (!aBuf) 5630Sstevel@tonic-gate return (GSS_S_FAILURE); 5640Sstevel@tonic-gate 5650Sstevel@tonic-gate if (addNullChar) 5660Sstevel@tonic-gate len = srcBuf->length + 1; 5670Sstevel@tonic-gate else 5680Sstevel@tonic-gate len = srcBuf->length; 5690Sstevel@tonic-gate 5700Sstevel@tonic-gate if (!(aBuf->value = (void*)malloc(len))) { 5710Sstevel@tonic-gate free(aBuf); 5720Sstevel@tonic-gate return (GSS_S_FAILURE); 5730Sstevel@tonic-gate } 5740Sstevel@tonic-gate 5750Sstevel@tonic-gate 5760Sstevel@tonic-gate (void) memcpy(aBuf->value, srcBuf->value, srcBuf->length); 5770Sstevel@tonic-gate aBuf->length = srcBuf->length; 5780Sstevel@tonic-gate *destBuf = aBuf; 5790Sstevel@tonic-gate 5800Sstevel@tonic-gate /* optionally add a NULL character */ 5810Sstevel@tonic-gate if (addNullChar) 5820Sstevel@tonic-gate ((char *)aBuf->value)[aBuf->length] = '\0'; 5830Sstevel@tonic-gate 5840Sstevel@tonic-gate return (GSS_S_COMPLETE); 5850Sstevel@tonic-gate } /* ****** __gss_create_copy_buffer ****** */ 586