10Sstevel@tonic-gate /* 2*10598SGlenn.Barry@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 30Sstevel@tonic-gate * Use is subject to license terms. 40Sstevel@tonic-gate */ 50Sstevel@tonic-gate 6*10598SGlenn.Barry@Sun.COM #include "mglueP.h" 70Sstevel@tonic-gate 80Sstevel@tonic-gate #include <stdio.h> 9*10598SGlenn.Barry@Sun.COM #ifdef HAVE_STDLIB_H 100Sstevel@tonic-gate #include <stdlib.h> 11*10598SGlenn.Barry@Sun.COM #endif 12*10598SGlenn.Barry@Sun.COM #include <string.h> 130Sstevel@tonic-gate #include <errno.h> 140Sstevel@tonic-gate 15*10598SGlenn.Barry@Sun.COM #include "k5-platform-store_32.h" 16*10598SGlenn.Barry@Sun.COM #include "k5-platform-store_16.h" 17*10598SGlenn.Barry@Sun.COM /* 18*10598SGlenn.Barry@Sun.COM * SUNW17PACresync 19*10598SGlenn.Barry@Sun.COM * MIT has diff names for these GSS utilities. Solaris needs to change 20*10598SGlenn.Barry@Sun.COM * them globally to get in sync w/MIT. 21*10598SGlenn.Barry@Sun.COM * Revisit for full 1.7 resync. 22*10598SGlenn.Barry@Sun.COM */ 23*10598SGlenn.Barry@Sun.COM #define gssint_get_modOptions __gss_get_modOptions 24*10598SGlenn.Barry@Sun.COM #define gssint_der_length_size der_length_size 25*10598SGlenn.Barry@Sun.COM #define gssint_get_der_length get_der_length 26*10598SGlenn.Barry@Sun.COM #define gssint_put_der_length put_der_length 27*10598SGlenn.Barry@Sun.COM #define gssint_get_mechanism __gss_get_mechanism 28*10598SGlenn.Barry@Sun.COM #define gssint_get_mechanism_cred __gss_get_mechanism_cred 29*10598SGlenn.Barry@Sun.COM #define gssint_copy_oid_set gss_copy_oid_set 30*10598SGlenn.Barry@Sun.COM #define gssint_get_mech_type __gss_get_mech_type 31*10598SGlenn.Barry@Sun.COM #define gssint_export_internal_name __gss_export_internal_name 32*10598SGlenn.Barry@Sun.COM #define gssint_release_internal_name __gss_release_internal_name 33*10598SGlenn.Barry@Sun.COM #define gssint_convert_name_to_union_name __gss_convert_name_to_union_name 34*10598SGlenn.Barry@Sun.COM #define gssint_import_internal_name __gss_import_internal_name 35*10598SGlenn.Barry@Sun.COM #define gssint_display_internal_name __gss_display_internal_name 36*10598SGlenn.Barry@Sun.COM 37*10598SGlenn.Barry@Sun.COM 380Sstevel@tonic-gate #define MSO_BIT (8*(sizeof (int) - 1)) /* Most significant octet bit */ 390Sstevel@tonic-gate 40*10598SGlenn.Barry@Sun.COM extern gss_mechanism *gssint_mechs_array; 41*10598SGlenn.Barry@Sun.COM 420Sstevel@tonic-gate /* 430Sstevel@tonic-gate * This file contains the support routines for the glue layer. 440Sstevel@tonic-gate */ 450Sstevel@tonic-gate 460Sstevel@tonic-gate /* 470Sstevel@tonic-gate * get_der_length: Givin a pointer to a buffer that contains a DER encoded 480Sstevel@tonic-gate * length, decode the length updating the buffer to point to the character 490Sstevel@tonic-gate * after the DER encoding. The parameter bytes will point to the number of 500Sstevel@tonic-gate * bytes that made up the DER encoding of the length originally pointed to 510Sstevel@tonic-gate * by the buffer. Note we return -1 on error. 520Sstevel@tonic-gate */ 530Sstevel@tonic-gate int 54*10598SGlenn.Barry@Sun.COM gssint_get_der_length(unsigned char **buf, unsigned int buf_len, unsigned int *bytes) 550Sstevel@tonic-gate { 56*10598SGlenn.Barry@Sun.COM /* p points to the beginning of the buffer */ 57*10598SGlenn.Barry@Sun.COM unsigned char *p = *buf; 58*10598SGlenn.Barry@Sun.COM int length, new_length; 59*10598SGlenn.Barry@Sun.COM unsigned int octets; 600Sstevel@tonic-gate 61*10598SGlenn.Barry@Sun.COM if (buf_len < 1) 62*10598SGlenn.Barry@Sun.COM return (-1); 630Sstevel@tonic-gate 64*10598SGlenn.Barry@Sun.COM /* We should have at least one byte */ 65*10598SGlenn.Barry@Sun.COM *bytes = 1; 660Sstevel@tonic-gate 67*10598SGlenn.Barry@Sun.COM /* 68*10598SGlenn.Barry@Sun.COM * If the High order bit is not set then the length is just the value 69*10598SGlenn.Barry@Sun.COM * of *p. 70*10598SGlenn.Barry@Sun.COM */ 71*10598SGlenn.Barry@Sun.COM if (*p < 128) { 72*10598SGlenn.Barry@Sun.COM *buf = p+1; /* Advance the buffer */ 730Sstevel@tonic-gate return (*p); /* return the length */ 74*10598SGlenn.Barry@Sun.COM } 750Sstevel@tonic-gate 76*10598SGlenn.Barry@Sun.COM /* 77*10598SGlenn.Barry@Sun.COM * if the High order bit is set, then the low order bits represent 78*10598SGlenn.Barry@Sun.COM * the number of bytes that contain the DER encoding of the length. 79*10598SGlenn.Barry@Sun.COM */ 800Sstevel@tonic-gate 81*10598SGlenn.Barry@Sun.COM octets = *p++ & 0x7f; 82*10598SGlenn.Barry@Sun.COM *bytes += octets; 830Sstevel@tonic-gate 84*10598SGlenn.Barry@Sun.COM /* See if the supplied buffer contains enough bytes for the length. */ 85*10598SGlenn.Barry@Sun.COM if (octets > buf_len - 1) 86*10598SGlenn.Barry@Sun.COM return (-1); 870Sstevel@tonic-gate 88*10598SGlenn.Barry@Sun.COM /* 89*10598SGlenn.Barry@Sun.COM * Calculate a multibyte length. The length is encoded as an 90*10598SGlenn.Barry@Sun.COM * unsigned integer base 256. 91*10598SGlenn.Barry@Sun.COM */ 92*10598SGlenn.Barry@Sun.COM for (length = 0; octets; octets--) { 93*10598SGlenn.Barry@Sun.COM new_length = (length << 8) + *p++; 94*10598SGlenn.Barry@Sun.COM if (new_length < length) /* overflow */ 95*10598SGlenn.Barry@Sun.COM return (-1); 96*10598SGlenn.Barry@Sun.COM length = new_length; 97*10598SGlenn.Barry@Sun.COM } 980Sstevel@tonic-gate 99*10598SGlenn.Barry@Sun.COM *buf = p; /* Advance the buffer */ 1000Sstevel@tonic-gate 101*10598SGlenn.Barry@Sun.COM return (length); 1020Sstevel@tonic-gate } 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate /* 1050Sstevel@tonic-gate * der_length_size: Return the number of bytes to encode a given length. 1060Sstevel@tonic-gate */ 1070Sstevel@tonic-gate unsigned int 108*10598SGlenn.Barry@Sun.COM gssint_der_length_size(unsigned int len) 1090Sstevel@tonic-gate { 110*10598SGlenn.Barry@Sun.COM int i; 1110Sstevel@tonic-gate 112*10598SGlenn.Barry@Sun.COM if (len < 128) 113*10598SGlenn.Barry@Sun.COM return (1); 1140Sstevel@tonic-gate 115*10598SGlenn.Barry@Sun.COM for (i = 0; len; i++) { 116*10598SGlenn.Barry@Sun.COM len >>= 8; 117*10598SGlenn.Barry@Sun.COM } 1180Sstevel@tonic-gate 119*10598SGlenn.Barry@Sun.COM return (i+1); 1200Sstevel@tonic-gate } 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate /* 1230Sstevel@tonic-gate * put_der_length: Encode the supplied length into the buffer pointed to 1240Sstevel@tonic-gate * by buf. max_length represents the maximum length of the buffer pointed 1250Sstevel@tonic-gate * to by buff. We will advance buf to point to the character after the newly 1260Sstevel@tonic-gate * DER encoded length. We return 0 on success or -l it the length cannot 1270Sstevel@tonic-gate * be encoded in max_len characters. 1280Sstevel@tonic-gate */ 1290Sstevel@tonic-gate int 130*10598SGlenn.Barry@Sun.COM gssint_put_der_length(unsigned int length, unsigned char **buf, unsigned int max_len) 1310Sstevel@tonic-gate { 132*10598SGlenn.Barry@Sun.COM unsigned char *s, *p; 133*10598SGlenn.Barry@Sun.COM unsigned int buf_len = 0; 134*10598SGlenn.Barry@Sun.COM int i, first; 1350Sstevel@tonic-gate 136*10598SGlenn.Barry@Sun.COM /* Oops */ 137*10598SGlenn.Barry@Sun.COM if (buf == 0 || max_len < 1) 138*10598SGlenn.Barry@Sun.COM return (-1); 139*10598SGlenn.Barry@Sun.COM 140*10598SGlenn.Barry@Sun.COM s = *buf; 1410Sstevel@tonic-gate 142*10598SGlenn.Barry@Sun.COM /* Single byte is the length */ 143*10598SGlenn.Barry@Sun.COM if (length < 128) { 144*10598SGlenn.Barry@Sun.COM *s++ = length; 145*10598SGlenn.Barry@Sun.COM *buf = s; 146*10598SGlenn.Barry@Sun.COM return (0); 147*10598SGlenn.Barry@Sun.COM } 1480Sstevel@tonic-gate 149*10598SGlenn.Barry@Sun.COM /* First byte contains the number of octets */ 150*10598SGlenn.Barry@Sun.COM p = s + 1; 1510Sstevel@tonic-gate 152*10598SGlenn.Barry@Sun.COM /* Running total of the DER encoding length */ 153*10598SGlenn.Barry@Sun.COM buf_len = 0; 1540Sstevel@tonic-gate 155*10598SGlenn.Barry@Sun.COM /* 156*10598SGlenn.Barry@Sun.COM * Encode MSB first. We do the encoding by setting a shift 157*10598SGlenn.Barry@Sun.COM * factor to MSO_BIT (24 for 32 bit words) and then shifting the length 158*10598SGlenn.Barry@Sun.COM * by the factor. We then encode the resulting low order byte. 159*10598SGlenn.Barry@Sun.COM * We subtract 8 from the shift factor and repeat to ecnode the next 160*10598SGlenn.Barry@Sun.COM * byte. We stop when the shift factor is zero or we've run out of 161*10598SGlenn.Barry@Sun.COM * buffer to encode into. 162*10598SGlenn.Barry@Sun.COM */ 163*10598SGlenn.Barry@Sun.COM first = 0; 164*10598SGlenn.Barry@Sun.COM for (i = MSO_BIT; i >= 0 && buf_len <= max_len; i -= 8) { 165*10598SGlenn.Barry@Sun.COM unsigned int v; 166*10598SGlenn.Barry@Sun.COM v = (length >> i) & 0xff; 167*10598SGlenn.Barry@Sun.COM if ((v) || first) { 168*10598SGlenn.Barry@Sun.COM buf_len += 1; 169*10598SGlenn.Barry@Sun.COM *p++ = v; 170*10598SGlenn.Barry@Sun.COM first = 1; 1710Sstevel@tonic-gate } 172*10598SGlenn.Barry@Sun.COM } 173*10598SGlenn.Barry@Sun.COM if (i >= 0) /* buffer overflow */ 174*10598SGlenn.Barry@Sun.COM return (-1); 1750Sstevel@tonic-gate 176*10598SGlenn.Barry@Sun.COM /* 177*10598SGlenn.Barry@Sun.COM * We go back now and set the first byte to be the length with 178*10598SGlenn.Barry@Sun.COM * the high order bit set. 179*10598SGlenn.Barry@Sun.COM */ 180*10598SGlenn.Barry@Sun.COM *s = buf_len | 0x80; 181*10598SGlenn.Barry@Sun.COM *buf = p; 1820Sstevel@tonic-gate 183*10598SGlenn.Barry@Sun.COM return (0); 1840Sstevel@tonic-gate } 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate /* 1880Sstevel@tonic-gate * glue routine for get_mech_type 1890Sstevel@tonic-gate * 1900Sstevel@tonic-gate */ 191*10598SGlenn.Barry@Sun.COM 192*10598SGlenn.Barry@Sun.COM OM_uint32 gssint_get_mech_type_oid(OID, token) 193*10598SGlenn.Barry@Sun.COM gss_OID OID; 194*10598SGlenn.Barry@Sun.COM gss_buffer_t token; 1950Sstevel@tonic-gate { 196*10598SGlenn.Barry@Sun.COM unsigned char * buffer_ptr; 197*10598SGlenn.Barry@Sun.COM int length; 198*10598SGlenn.Barry@Sun.COM 199*10598SGlenn.Barry@Sun.COM /* 200*10598SGlenn.Barry@Sun.COM * This routine reads the prefix of "token" in order to determine 201*10598SGlenn.Barry@Sun.COM * its mechanism type. It assumes the encoding suggested in 202*10598SGlenn.Barry@Sun.COM * Appendix B of RFC 1508. This format starts out as follows : 203*10598SGlenn.Barry@Sun.COM * 204*10598SGlenn.Barry@Sun.COM * tag for APPLICATION 0, Sequence[constructed, definite length] 205*10598SGlenn.Barry@Sun.COM * length of remainder of token 206*10598SGlenn.Barry@Sun.COM * tag of OBJECT IDENTIFIER 207*10598SGlenn.Barry@Sun.COM * length of mechanism OID 208*10598SGlenn.Barry@Sun.COM * encoding of mechanism OID 209*10598SGlenn.Barry@Sun.COM * <the rest of the token> 210*10598SGlenn.Barry@Sun.COM * 211*10598SGlenn.Barry@Sun.COM * Numerically, this looks like : 212*10598SGlenn.Barry@Sun.COM * 213*10598SGlenn.Barry@Sun.COM * 0x60 214*10598SGlenn.Barry@Sun.COM * <length> - could be multiple bytes 215*10598SGlenn.Barry@Sun.COM * 0x06 216*10598SGlenn.Barry@Sun.COM * <length> - assume only one byte, hence OID length < 127 217*10598SGlenn.Barry@Sun.COM * <mech OID bytes> 218*10598SGlenn.Barry@Sun.COM * 219*10598SGlenn.Barry@Sun.COM * The routine fills in the OID value and returns an error as necessary. 220*10598SGlenn.Barry@Sun.COM */ 221*10598SGlenn.Barry@Sun.COM 2220Sstevel@tonic-gate if (OID == NULL) 2230Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE); 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate if ((token == NULL) || (token->value == NULL)) 226*10598SGlenn.Barry@Sun.COM return (GSS_S_DEFECTIVE_TOKEN); 227*10598SGlenn.Barry@Sun.COM 228*10598SGlenn.Barry@Sun.COM /* Skip past the APP/Sequnce byte and the token length */ 229*10598SGlenn.Barry@Sun.COM 230*10598SGlenn.Barry@Sun.COM buffer_ptr = (unsigned char *) token->value; 2310Sstevel@tonic-gate 232*10598SGlenn.Barry@Sun.COM if (*(buffer_ptr++) != 0x60) 233*10598SGlenn.Barry@Sun.COM return (GSS_S_DEFECTIVE_TOKEN); 234*10598SGlenn.Barry@Sun.COM length = *buffer_ptr++; 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate /* check if token length is null */ 2370Sstevel@tonic-gate if (length == 0) 2380Sstevel@tonic-gate return (GSS_S_DEFECTIVE_TOKEN); 2390Sstevel@tonic-gate 240*10598SGlenn.Barry@Sun.COM if (length & 0x80) { 241*10598SGlenn.Barry@Sun.COM if ((length & 0x7f) > 4) 242*10598SGlenn.Barry@Sun.COM return (GSS_S_DEFECTIVE_TOKEN); 243*10598SGlenn.Barry@Sun.COM buffer_ptr += length & 0x7f; 244*10598SGlenn.Barry@Sun.COM } 245*10598SGlenn.Barry@Sun.COM 246*10598SGlenn.Barry@Sun.COM if (*(buffer_ptr++) != 0x06) 247*10598SGlenn.Barry@Sun.COM return (GSS_S_DEFECTIVE_TOKEN); 248*10598SGlenn.Barry@Sun.COM 249*10598SGlenn.Barry@Sun.COM OID->length = (OM_uint32) *(buffer_ptr++); 250*10598SGlenn.Barry@Sun.COM OID->elements = (void *) buffer_ptr; 251*10598SGlenn.Barry@Sun.COM return (GSS_S_COMPLETE); 252*10598SGlenn.Barry@Sun.COM } 2530Sstevel@tonic-gate 254*10598SGlenn.Barry@Sun.COM /* 255*10598SGlenn.Barry@Sun.COM * The following mechanisms do not always identify themselves 256*10598SGlenn.Barry@Sun.COM * per the GSS-API specification, when interoperating with MS 257*10598SGlenn.Barry@Sun.COM * peers. We include the OIDs here so we do not have to link 258*10598SGlenn.Barry@Sun.COM * with the mechanism. 259*10598SGlenn.Barry@Sun.COM */ 260*10598SGlenn.Barry@Sun.COM static gss_OID_desc gss_ntlm_mechanism_oid_desc = 261*10598SGlenn.Barry@Sun.COM {10, (void *)"\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"}; 262*10598SGlenn.Barry@Sun.COM static gss_OID_desc gss_spnego_mechanism_oid_desc = 263*10598SGlenn.Barry@Sun.COM {6, (void *)"\x2b\x06\x01\x05\x05\x02"}; 264*10598SGlenn.Barry@Sun.COM static gss_OID_desc gss_krb5_mechanism_oid_desc = 265*10598SGlenn.Barry@Sun.COM {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"}; 266*10598SGlenn.Barry@Sun.COM 267*10598SGlenn.Barry@Sun.COM #define NTLMSSP_SIGNATURE "NTLMSSP" 2680Sstevel@tonic-gate 269*10598SGlenn.Barry@Sun.COM OM_uint32 gssint_get_mech_type(OID, token) 270*10598SGlenn.Barry@Sun.COM gss_OID OID; 271*10598SGlenn.Barry@Sun.COM gss_buffer_t token; 272*10598SGlenn.Barry@Sun.COM { 273*10598SGlenn.Barry@Sun.COM /* Check for interoperability exceptions */ 274*10598SGlenn.Barry@Sun.COM if (token->length >= sizeof(NTLMSSP_SIGNATURE) && 275*10598SGlenn.Barry@Sun.COM memcmp(token->value, NTLMSSP_SIGNATURE, 276*10598SGlenn.Barry@Sun.COM sizeof(NTLMSSP_SIGNATURE)) == 0) { 277*10598SGlenn.Barry@Sun.COM *OID = gss_ntlm_mechanism_oid_desc; 278*10598SGlenn.Barry@Sun.COM } else if (token->length != 0 && 279*10598SGlenn.Barry@Sun.COM ((char *)token->value)[0] == 0x6E) { 280*10598SGlenn.Barry@Sun.COM /* Could be a raw AP-REQ (check for APPLICATION tag) */ 281*10598SGlenn.Barry@Sun.COM *OID = gss_krb5_mechanism_oid_desc; 282*10598SGlenn.Barry@Sun.COM } else if (token->length == 0) { 283*10598SGlenn.Barry@Sun.COM *OID = gss_spnego_mechanism_oid_desc; 284*10598SGlenn.Barry@Sun.COM } else { 285*10598SGlenn.Barry@Sun.COM return gssint_get_mech_type_oid(OID, token); 286*10598SGlenn.Barry@Sun.COM } 287*10598SGlenn.Barry@Sun.COM 288*10598SGlenn.Barry@Sun.COM return (GSS_S_COMPLETE); 2890Sstevel@tonic-gate } 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate /* 2930Sstevel@tonic-gate * Internal routines to get and release an internal mechanism name 2940Sstevel@tonic-gate */ 295*10598SGlenn.Barry@Sun.COM 296*10598SGlenn.Barry@Sun.COM #if 0 /* SUNW17PACresync */ 297*10598SGlenn.Barry@Sun.COM #include "mglueP.h" 298*10598SGlenn.Barry@Sun.COM #endif 299*10598SGlenn.Barry@Sun.COM 300*10598SGlenn.Barry@Sun.COM OM_uint32 gssint_import_internal_name (minor_status, mech_type, union_name, 301*10598SGlenn.Barry@Sun.COM internal_name) 3020Sstevel@tonic-gate OM_uint32 *minor_status; 303*10598SGlenn.Barry@Sun.COM gss_OID mech_type; 3040Sstevel@tonic-gate gss_union_name_t union_name; 3050Sstevel@tonic-gate gss_name_t *internal_name; 3060Sstevel@tonic-gate { 307*10598SGlenn.Barry@Sun.COM OM_uint32 status; 308*10598SGlenn.Barry@Sun.COM gss_mechanism mech; 3090Sstevel@tonic-gate 310*10598SGlenn.Barry@Sun.COM mech = gssint_get_mechanism (mech_type); 311*10598SGlenn.Barry@Sun.COM if (mech) { 312*10598SGlenn.Barry@Sun.COM if (mech->gss_import_name) { 313*10598SGlenn.Barry@Sun.COM status = mech->gss_import_name ( 314*10598SGlenn.Barry@Sun.COM mech->context, /* SUNW17PACresync */ 315*10598SGlenn.Barry@Sun.COM minor_status, 316*10598SGlenn.Barry@Sun.COM union_name->external_name, 317*10598SGlenn.Barry@Sun.COM union_name->name_type, 318*10598SGlenn.Barry@Sun.COM internal_name); 319*10598SGlenn.Barry@Sun.COM if (status != GSS_S_COMPLETE) 320*10598SGlenn.Barry@Sun.COM map_error(minor_status, mech); 321*10598SGlenn.Barry@Sun.COM } else 322*10598SGlenn.Barry@Sun.COM status = GSS_S_UNAVAILABLE; 3230Sstevel@tonic-gate 324*10598SGlenn.Barry@Sun.COM return (status); 325*10598SGlenn.Barry@Sun.COM } 3260Sstevel@tonic-gate 327*10598SGlenn.Barry@Sun.COM return (GSS_S_BAD_MECH); 3280Sstevel@tonic-gate } 3290Sstevel@tonic-gate 330*10598SGlenn.Barry@Sun.COM OM_uint32 gssint_export_internal_name(minor_status, mech_type, 331*10598SGlenn.Barry@Sun.COM internal_name, name_buf) 332*10598SGlenn.Barry@Sun.COM OM_uint32 *minor_status; 333*10598SGlenn.Barry@Sun.COM const gss_OID mech_type; 334*10598SGlenn.Barry@Sun.COM const gss_name_t internal_name; 335*10598SGlenn.Barry@Sun.COM gss_buffer_t name_buf; 3360Sstevel@tonic-gate { 337*10598SGlenn.Barry@Sun.COM OM_uint32 status; 338*10598SGlenn.Barry@Sun.COM gss_mechanism mech; 339*10598SGlenn.Barry@Sun.COM gss_buffer_desc dispName; 340*10598SGlenn.Barry@Sun.COM gss_OID nameOid; 341*10598SGlenn.Barry@Sun.COM unsigned char *buf = NULL; 342*10598SGlenn.Barry@Sun.COM const unsigned char tokId[] = "\x04\x01"; 343*10598SGlenn.Barry@Sun.COM const unsigned int tokIdLen = 2; 344*10598SGlenn.Barry@Sun.COM const int mechOidLenLen = 2, mechOidTagLen = 1, nameLenLen = 4; 345*10598SGlenn.Barry@Sun.COM int mechOidDERLen = 0; 346*10598SGlenn.Barry@Sun.COM int mechOidLen = 0; 3470Sstevel@tonic-gate 348*10598SGlenn.Barry@Sun.COM mech = gssint_get_mechanism(mech_type); 349*10598SGlenn.Barry@Sun.COM if (!mech) 350*10598SGlenn.Barry@Sun.COM return (GSS_S_BAD_MECH); 3510Sstevel@tonic-gate 352*10598SGlenn.Barry@Sun.COM if (mech->gss_export_name) { 353*10598SGlenn.Barry@Sun.COM status = mech->gss_export_name( 354*10598SGlenn.Barry@Sun.COM mech->context, /* SUNW17PACresync */ 355*10598SGlenn.Barry@Sun.COM minor_status, 356*10598SGlenn.Barry@Sun.COM internal_name, 357*10598SGlenn.Barry@Sun.COM name_buf); 358*10598SGlenn.Barry@Sun.COM if (status != GSS_S_COMPLETE) 359*10598SGlenn.Barry@Sun.COM map_error(minor_status, mech); 360*10598SGlenn.Barry@Sun.COM return status; 361*10598SGlenn.Barry@Sun.COM } 3620Sstevel@tonic-gate 363*10598SGlenn.Barry@Sun.COM /* 364*10598SGlenn.Barry@Sun.COM * if we are here it is because the mechanism does not provide 365*10598SGlenn.Barry@Sun.COM * a gss_export_name so we will use our implementation. We 366*10598SGlenn.Barry@Sun.COM * do required that the mechanism define a gss_display_name. 367*10598SGlenn.Barry@Sun.COM */ 368*10598SGlenn.Barry@Sun.COM if (!mech->gss_display_name) 369*10598SGlenn.Barry@Sun.COM return (GSS_S_UNAVAILABLE); 3700Sstevel@tonic-gate 371*10598SGlenn.Barry@Sun.COM /* 372*10598SGlenn.Barry@Sun.COM * NOTE: RFC2743 (section 3.2) governs the format of the outer 373*10598SGlenn.Barry@Sun.COM * wrapper of exported names; the mechanisms' specs govern 374*10598SGlenn.Barry@Sun.COM * the format of the inner portion of the exported name 375*10598SGlenn.Barry@Sun.COM * and, for some (e.g., RFC1964, the Kerberos V mech), a 376*10598SGlenn.Barry@Sun.COM * generic default as implemented here will do. 377*10598SGlenn.Barry@Sun.COM * 378*10598SGlenn.Barry@Sun.COM * The outer wrapper of an exported MN is: 2-octet tok Id 379*10598SGlenn.Barry@Sun.COM * (0x0401) + 2-octet network-byte order mech OID length + mech 380*10598SGlenn.Barry@Sun.COM * oid (in DER format, including DER tag and DER length) + 381*10598SGlenn.Barry@Sun.COM * 4-octet network-byte order length of inner portion + inner 382*10598SGlenn.Barry@Sun.COM * portion. 383*10598SGlenn.Barry@Sun.COM * 384*10598SGlenn.Barry@Sun.COM * For the Kerberos V mechanism the inner portion of an exported 385*10598SGlenn.Barry@Sun.COM * MN is the display name string and ignores the name type OID 386*10598SGlenn.Barry@Sun.COM * altogether. And we hope this will be so for any future 387*10598SGlenn.Barry@Sun.COM * mechanisms also, so that factoring name export/import out of 388*10598SGlenn.Barry@Sun.COM * the mech and into libgss pays off. 389*10598SGlenn.Barry@Sun.COM */ 390*10598SGlenn.Barry@Sun.COM if ((status = mech->gss_display_name( 391*10598SGlenn.Barry@Sun.COM mech->context, 392*10598SGlenn.Barry@Sun.COM minor_status, 393*10598SGlenn.Barry@Sun.COM internal_name, 394*10598SGlenn.Barry@Sun.COM &dispName, 395*10598SGlenn.Barry@Sun.COM &nameOid)) 396*10598SGlenn.Barry@Sun.COM != GSS_S_COMPLETE) { 397*10598SGlenn.Barry@Sun.COM map_error(minor_status, mech); 398*10598SGlenn.Barry@Sun.COM return (status); 399*10598SGlenn.Barry@Sun.COM } 4000Sstevel@tonic-gate 401*10598SGlenn.Barry@Sun.COM /* determine the size of the buffer needed */ 402*10598SGlenn.Barry@Sun.COM mechOidDERLen = gssint_der_length_size(mech_type->length); 403*10598SGlenn.Barry@Sun.COM name_buf->length = tokIdLen + mechOidLenLen + 404*10598SGlenn.Barry@Sun.COM mechOidTagLen + mechOidDERLen + 405*10598SGlenn.Barry@Sun.COM mech_type->length + 406*10598SGlenn.Barry@Sun.COM nameLenLen + dispName.length; 407*10598SGlenn.Barry@Sun.COM if ((name_buf->value = (void*)malloc(name_buf->length)) == 408*10598SGlenn.Barry@Sun.COM (void*)NULL) { 409*10598SGlenn.Barry@Sun.COM name_buf->length = 0; 410*10598SGlenn.Barry@Sun.COM (void) gss_release_buffer(&status, &dispName); 411*10598SGlenn.Barry@Sun.COM return (GSS_S_FAILURE); 412*10598SGlenn.Barry@Sun.COM } 4130Sstevel@tonic-gate 414*10598SGlenn.Barry@Sun.COM /* now create the name ..... */ 415*10598SGlenn.Barry@Sun.COM buf = (unsigned char *)name_buf->value; 416*10598SGlenn.Barry@Sun.COM (void) memset(name_buf->value, 0, name_buf->length); 417*10598SGlenn.Barry@Sun.COM (void) memcpy(buf, tokId, tokIdLen); 418*10598SGlenn.Barry@Sun.COM buf += tokIdLen; 4190Sstevel@tonic-gate 420*10598SGlenn.Barry@Sun.COM /* spec allows only 2 bytes for the mech oid length */ 421*10598SGlenn.Barry@Sun.COM mechOidLen = mechOidDERLen + mechOidTagLen + mech_type->length; 422*10598SGlenn.Barry@Sun.COM store_16_be(mechOidLen, buf); 423*10598SGlenn.Barry@Sun.COM buf += 2; 4240Sstevel@tonic-gate 425*10598SGlenn.Barry@Sun.COM /* 426*10598SGlenn.Barry@Sun.COM * DER Encoding of mech OID contains OID Tag (0x06), length and 427*10598SGlenn.Barry@Sun.COM * mech OID value 428*10598SGlenn.Barry@Sun.COM */ 429*10598SGlenn.Barry@Sun.COM *buf++ = 0x06; 430*10598SGlenn.Barry@Sun.COM if (gssint_put_der_length(mech_type->length, &buf, 431*10598SGlenn.Barry@Sun.COM (name_buf->length - tokIdLen -2)) != 0) { 432*10598SGlenn.Barry@Sun.COM name_buf->length = 0; 433*10598SGlenn.Barry@Sun.COM free(name_buf->value); 434*10598SGlenn.Barry@Sun.COM (void) gss_release_buffer(&status, &dispName); 435*10598SGlenn.Barry@Sun.COM return (GSS_S_FAILURE); 436*10598SGlenn.Barry@Sun.COM } 4370Sstevel@tonic-gate 438*10598SGlenn.Barry@Sun.COM (void) memcpy(buf, mech_type->elements, mech_type->length); 439*10598SGlenn.Barry@Sun.COM buf += mech_type->length; 4400Sstevel@tonic-gate 441*10598SGlenn.Barry@Sun.COM /* spec designates the next 4 bytes for the name length */ 442*10598SGlenn.Barry@Sun.COM store_32_be(dispName.length, buf); 443*10598SGlenn.Barry@Sun.COM buf += 4; 4440Sstevel@tonic-gate 445*10598SGlenn.Barry@Sun.COM /* for the final ingredient - add the name from gss_display_name */ 446*10598SGlenn.Barry@Sun.COM (void) memcpy(buf, dispName.value, dispName.length); 4470Sstevel@tonic-gate 448*10598SGlenn.Barry@Sun.COM /* release the buffer obtained from gss_display_name */ 449*10598SGlenn.Barry@Sun.COM (void) gss_release_buffer(minor_status, &dispName); 450*10598SGlenn.Barry@Sun.COM return (GSS_S_COMPLETE); 451*10598SGlenn.Barry@Sun.COM } /* gssint_export_internal_name */ 4520Sstevel@tonic-gate 453*10598SGlenn.Barry@Sun.COM OM_uint32 gssint_display_internal_name (minor_status, mech_type, internal_name, 454*10598SGlenn.Barry@Sun.COM external_name, name_type) 455*10598SGlenn.Barry@Sun.COM OM_uint32 *minor_status; 456*10598SGlenn.Barry@Sun.COM gss_OID mech_type; 457*10598SGlenn.Barry@Sun.COM gss_name_t internal_name; 458*10598SGlenn.Barry@Sun.COM gss_buffer_t external_name; 459*10598SGlenn.Barry@Sun.COM gss_OID *name_type; 4600Sstevel@tonic-gate { 461*10598SGlenn.Barry@Sun.COM OM_uint32 status; 462*10598SGlenn.Barry@Sun.COM gss_mechanism mech; 4630Sstevel@tonic-gate 464*10598SGlenn.Barry@Sun.COM mech = gssint_get_mechanism (mech_type); 465*10598SGlenn.Barry@Sun.COM if (mech) { 466*10598SGlenn.Barry@Sun.COM if (mech->gss_display_name) { 467*10598SGlenn.Barry@Sun.COM status = mech->gss_display_name ( 468*10598SGlenn.Barry@Sun.COM mech->context, 469*10598SGlenn.Barry@Sun.COM minor_status, 470*10598SGlenn.Barry@Sun.COM internal_name, 471*10598SGlenn.Barry@Sun.COM external_name, 472*10598SGlenn.Barry@Sun.COM name_type); 473*10598SGlenn.Barry@Sun.COM if (status != GSS_S_COMPLETE) 474*10598SGlenn.Barry@Sun.COM map_error(minor_status, mech); 475*10598SGlenn.Barry@Sun.COM } else 476*10598SGlenn.Barry@Sun.COM status = GSS_S_UNAVAILABLE; 4770Sstevel@tonic-gate 478*10598SGlenn.Barry@Sun.COM return (status); 479*10598SGlenn.Barry@Sun.COM } 4800Sstevel@tonic-gate 481*10598SGlenn.Barry@Sun.COM return (GSS_S_BAD_MECH); 4820Sstevel@tonic-gate } 4830Sstevel@tonic-gate 484*10598SGlenn.Barry@Sun.COM OM_uint32 gssint_release_internal_name (minor_status, mech_type, internal_name) 485*10598SGlenn.Barry@Sun.COM OM_uint32 *minor_status; 486*10598SGlenn.Barry@Sun.COM gss_OID mech_type; 487*10598SGlenn.Barry@Sun.COM gss_name_t *internal_name; 4880Sstevel@tonic-gate { 489*10598SGlenn.Barry@Sun.COM OM_uint32 status; 490*10598SGlenn.Barry@Sun.COM gss_mechanism mech; 4910Sstevel@tonic-gate 492*10598SGlenn.Barry@Sun.COM mech = gssint_get_mechanism (mech_type); 493*10598SGlenn.Barry@Sun.COM if (mech) { 494*10598SGlenn.Barry@Sun.COM if (mech->gss_release_name) { 495*10598SGlenn.Barry@Sun.COM status = mech->gss_release_name ( 496*10598SGlenn.Barry@Sun.COM mech->context, 497*10598SGlenn.Barry@Sun.COM minor_status, 498*10598SGlenn.Barry@Sun.COM internal_name); 499*10598SGlenn.Barry@Sun.COM if (status != GSS_S_COMPLETE) 500*10598SGlenn.Barry@Sun.COM map_error(minor_status, mech); 501*10598SGlenn.Barry@Sun.COM } else 502*10598SGlenn.Barry@Sun.COM status = GSS_S_UNAVAILABLE; 5030Sstevel@tonic-gate 504*10598SGlenn.Barry@Sun.COM return (status); 505*10598SGlenn.Barry@Sun.COM } 5060Sstevel@tonic-gate 507*10598SGlenn.Barry@Sun.COM return (GSS_S_BAD_MECH); 5080Sstevel@tonic-gate } 5090Sstevel@tonic-gate 510*10598SGlenn.Barry@Sun.COM OM_uint32 gssint_delete_internal_sec_context (minor_status, 511*10598SGlenn.Barry@Sun.COM mech_type, 512*10598SGlenn.Barry@Sun.COM internal_ctx, 513*10598SGlenn.Barry@Sun.COM output_token) 514*10598SGlenn.Barry@Sun.COM OM_uint32 *minor_status; 515*10598SGlenn.Barry@Sun.COM gss_OID mech_type; 516*10598SGlenn.Barry@Sun.COM gss_ctx_id_t *internal_ctx; 517*10598SGlenn.Barry@Sun.COM gss_buffer_t output_token; 518*10598SGlenn.Barry@Sun.COM { 519*10598SGlenn.Barry@Sun.COM OM_uint32 status; 520*10598SGlenn.Barry@Sun.COM gss_mechanism mech; 521*10598SGlenn.Barry@Sun.COM 522*10598SGlenn.Barry@Sun.COM mech = gssint_get_mechanism (mech_type); 523*10598SGlenn.Barry@Sun.COM if (mech) { 524*10598SGlenn.Barry@Sun.COM if (mech->gss_delete_sec_context) 525*10598SGlenn.Barry@Sun.COM status = mech->gss_delete_sec_context ( 526*10598SGlenn.Barry@Sun.COM mech->context, /* SUNW17PACresync */ 527*10598SGlenn.Barry@Sun.COM minor_status, 528*10598SGlenn.Barry@Sun.COM internal_ctx, 529*10598SGlenn.Barry@Sun.COM output_token); 530*10598SGlenn.Barry@Sun.COM else 531*10598SGlenn.Barry@Sun.COM /* SUNW17PACresync - map error here? */ 532*10598SGlenn.Barry@Sun.COM status = GSS_S_UNAVAILABLE; 533*10598SGlenn.Barry@Sun.COM 534*10598SGlenn.Barry@Sun.COM return (status); 535*10598SGlenn.Barry@Sun.COM } 536*10598SGlenn.Barry@Sun.COM 537*10598SGlenn.Barry@Sun.COM return (GSS_S_BAD_MECH); 538*10598SGlenn.Barry@Sun.COM } 5390Sstevel@tonic-gate 5400Sstevel@tonic-gate /* 5410Sstevel@tonic-gate * This function converts an internal gssapi name to a union gssapi 5420Sstevel@tonic-gate * name. Note that internal_name should be considered "consumed" by 5430Sstevel@tonic-gate * this call, whether or not we return an error. 5440Sstevel@tonic-gate */ 545*10598SGlenn.Barry@Sun.COM OM_uint32 gssint_convert_name_to_union_name(minor_status, mech, 546*10598SGlenn.Barry@Sun.COM internal_name, external_name) 547*10598SGlenn.Barry@Sun.COM OM_uint32 *minor_status; 548*10598SGlenn.Barry@Sun.COM gss_mechanism mech; 549*10598SGlenn.Barry@Sun.COM gss_name_t internal_name; 550*10598SGlenn.Barry@Sun.COM gss_name_t *external_name; 5510Sstevel@tonic-gate { 552*10598SGlenn.Barry@Sun.COM OM_uint32 major_status,tmp; 553*10598SGlenn.Barry@Sun.COM gss_union_name_t union_name; 5540Sstevel@tonic-gate 555*10598SGlenn.Barry@Sun.COM union_name = (gss_union_name_t) malloc (sizeof(gss_union_name_desc)); 556*10598SGlenn.Barry@Sun.COM if (!union_name) { 557*10598SGlenn.Barry@Sun.COM major_status = GSS_S_FAILURE; 558*10598SGlenn.Barry@Sun.COM *minor_status = ENOMEM; 559*10598SGlenn.Barry@Sun.COM map_errcode(minor_status); 560*10598SGlenn.Barry@Sun.COM goto allocation_failure; 561*10598SGlenn.Barry@Sun.COM } 562*10598SGlenn.Barry@Sun.COM union_name->mech_type = 0; 563*10598SGlenn.Barry@Sun.COM union_name->mech_name = internal_name; 564*10598SGlenn.Barry@Sun.COM union_name->name_type = 0; 565*10598SGlenn.Barry@Sun.COM union_name->external_name = 0; 5660Sstevel@tonic-gate 567*10598SGlenn.Barry@Sun.COM major_status = generic_gss_copy_oid(minor_status, &mech->mech_type, 568*10598SGlenn.Barry@Sun.COM &union_name->mech_type); 569*10598SGlenn.Barry@Sun.COM if (major_status != GSS_S_COMPLETE) { 570*10598SGlenn.Barry@Sun.COM map_errcode(minor_status); 571*10598SGlenn.Barry@Sun.COM goto allocation_failure; 572*10598SGlenn.Barry@Sun.COM } 5730Sstevel@tonic-gate 574*10598SGlenn.Barry@Sun.COM union_name->external_name = 575*10598SGlenn.Barry@Sun.COM (gss_buffer_t) malloc(sizeof(gss_buffer_desc)); 576*10598SGlenn.Barry@Sun.COM if (!union_name->external_name) { 577*10598SGlenn.Barry@Sun.COM major_status = GSS_S_FAILURE; 578*10598SGlenn.Barry@Sun.COM *minor_status = ENOMEM; 579*10598SGlenn.Barry@Sun.COM goto allocation_failure; 580*10598SGlenn.Barry@Sun.COM } 581*10598SGlenn.Barry@Sun.COM 582*10598SGlenn.Barry@Sun.COM major_status = mech->gss_display_name( 583*10598SGlenn.Barry@Sun.COM mech->context, /* SUNW17PACresync */ 584*10598SGlenn.Barry@Sun.COM minor_status, 585*10598SGlenn.Barry@Sun.COM internal_name, 586*10598SGlenn.Barry@Sun.COM union_name->external_name, 587*10598SGlenn.Barry@Sun.COM &union_name->name_type); 588*10598SGlenn.Barry@Sun.COM if (major_status != GSS_S_COMPLETE) { 589*10598SGlenn.Barry@Sun.COM map_error(minor_status, mech); 590*10598SGlenn.Barry@Sun.COM goto allocation_failure; 591*10598SGlenn.Barry@Sun.COM } 5920Sstevel@tonic-gate 593*10598SGlenn.Barry@Sun.COM union_name->loopback = union_name; 594*10598SGlenn.Barry@Sun.COM *external_name = (gss_name_t) union_name; 595*10598SGlenn.Barry@Sun.COM return (GSS_S_COMPLETE); 5960Sstevel@tonic-gate 5970Sstevel@tonic-gate allocation_failure: 598*10598SGlenn.Barry@Sun.COM if (union_name) { 599*10598SGlenn.Barry@Sun.COM if (union_name->external_name) { 600*10598SGlenn.Barry@Sun.COM if (union_name->external_name->value) 601*10598SGlenn.Barry@Sun.COM free(union_name->external_name->value); 602*10598SGlenn.Barry@Sun.COM free(union_name->external_name); 6030Sstevel@tonic-gate } 604*10598SGlenn.Barry@Sun.COM if (union_name->name_type) 605*10598SGlenn.Barry@Sun.COM (void) gss_release_oid(&tmp, &union_name->name_type); 606*10598SGlenn.Barry@Sun.COM if (union_name->mech_type) 607*10598SGlenn.Barry@Sun.COM (void) gss_release_oid(&tmp, &union_name->mech_type); 608*10598SGlenn.Barry@Sun.COM free(union_name); 609*10598SGlenn.Barry@Sun.COM } 610*10598SGlenn.Barry@Sun.COM /* 611*10598SGlenn.Barry@Sun.COM * do as the top comment says - since we are now owners of 612*10598SGlenn.Barry@Sun.COM * internal_name, we must clean it up 613*10598SGlenn.Barry@Sun.COM */ 614*10598SGlenn.Barry@Sun.COM if (internal_name) 615*10598SGlenn.Barry@Sun.COM (void) gssint_release_internal_name(&tmp, &mech->mech_type, 616*10598SGlenn.Barry@Sun.COM &internal_name); 617*10598SGlenn.Barry@Sun.COM return (major_status); 6180Sstevel@tonic-gate } 6190Sstevel@tonic-gate 6200Sstevel@tonic-gate /* 6210Sstevel@tonic-gate * Glue routine for returning the mechanism-specific credential from a 6220Sstevel@tonic-gate * external union credential. 6230Sstevel@tonic-gate */ 6240Sstevel@tonic-gate gss_cred_id_t 625*10598SGlenn.Barry@Sun.COM gssint_get_mechanism_cred(union_cred, mech_type) 626*10598SGlenn.Barry@Sun.COM gss_union_cred_t union_cred; 627*10598SGlenn.Barry@Sun.COM gss_OID mech_type; 6280Sstevel@tonic-gate { 629*10598SGlenn.Barry@Sun.COM int i; 630*10598SGlenn.Barry@Sun.COM 631*10598SGlenn.Barry@Sun.COM if (union_cred == (gss_union_cred_t) GSS_C_NO_CREDENTIAL) 632*10598SGlenn.Barry@Sun.COM return GSS_C_NO_CREDENTIAL; 633*10598SGlenn.Barry@Sun.COM 634*10598SGlenn.Barry@Sun.COM /* 635*10598SGlenn.Barry@Sun.COM * SUNW17PACresync 636*10598SGlenn.Barry@Sun.COM * Disable this block as it causes problems for gss_add_cred 637*10598SGlenn.Barry@Sun.COM * for HTTP SSO (and also probably causes STC gss.13 to fail too). 638*10598SGlenn.Barry@Sun.COM */ 639*10598SGlenn.Barry@Sun.COM #if 0 640*10598SGlenn.Barry@Sun.COM /* SPNEGO mechanism will again call into GSSAPI */ 641*10598SGlenn.Barry@Sun.COM if (g_OID_equal(&gss_spnego_mechanism_oid_desc, mech_type)) 642*10598SGlenn.Barry@Sun.COM return (gss_cred_id_t)union_cred; 643*10598SGlenn.Barry@Sun.COM #endif 6440Sstevel@tonic-gate 645*10598SGlenn.Barry@Sun.COM for (i=0; i < union_cred->count; i++) { 646*10598SGlenn.Barry@Sun.COM if (g_OID_equal(mech_type, &union_cred->mechs_array[i])) 647*10598SGlenn.Barry@Sun.COM return union_cred->cred_array[i]; 648*10598SGlenn.Barry@Sun.COM 649*10598SGlenn.Barry@Sun.COM /* for SPNEGO, check the next-lower set of creds */ 650*10598SGlenn.Barry@Sun.COM if (g_OID_equal(&gss_spnego_mechanism_oid_desc, &union_cred->mechs_array[i])) { 651*10598SGlenn.Barry@Sun.COM gss_union_cred_t candidate_cred; 652*10598SGlenn.Barry@Sun.COM gss_cred_id_t sub_cred; 6530Sstevel@tonic-gate 654*10598SGlenn.Barry@Sun.COM candidate_cred = (gss_union_cred_t)union_cred->cred_array[i]; 655*10598SGlenn.Barry@Sun.COM sub_cred = gssint_get_mechanism_cred(candidate_cred, mech_type); 656*10598SGlenn.Barry@Sun.COM 657*10598SGlenn.Barry@Sun.COM if(sub_cred != GSS_C_NO_CREDENTIAL) 658*10598SGlenn.Barry@Sun.COM return sub_cred; 6590Sstevel@tonic-gate } 660*10598SGlenn.Barry@Sun.COM } 661*10598SGlenn.Barry@Sun.COM 662*10598SGlenn.Barry@Sun.COM return GSS_C_NO_CREDENTIAL; 6630Sstevel@tonic-gate } 6640Sstevel@tonic-gate 6650Sstevel@tonic-gate /* 6660Sstevel@tonic-gate * Routine to create and copy the gss_buffer_desc structure. 6670Sstevel@tonic-gate * Both space for the structure and the data is allocated. 6680Sstevel@tonic-gate */ 6690Sstevel@tonic-gate OM_uint32 6705053Sgtb gssint_create_copy_buffer(srcBuf, destBuf, addNullChar) 671*10598SGlenn.Barry@Sun.COM const gss_buffer_t srcBuf; 672*10598SGlenn.Barry@Sun.COM gss_buffer_t *destBuf; 673*10598SGlenn.Barry@Sun.COM int addNullChar; 6740Sstevel@tonic-gate { 675*10598SGlenn.Barry@Sun.COM gss_buffer_t aBuf; 676*10598SGlenn.Barry@Sun.COM unsigned int len; 6770Sstevel@tonic-gate 678*10598SGlenn.Barry@Sun.COM if (destBuf == NULL) 679*10598SGlenn.Barry@Sun.COM return (GSS_S_CALL_INACCESSIBLE_WRITE); 6800Sstevel@tonic-gate 681*10598SGlenn.Barry@Sun.COM *destBuf = 0; 6820Sstevel@tonic-gate 683*10598SGlenn.Barry@Sun.COM aBuf = (gss_buffer_t)malloc(sizeof (gss_buffer_desc)); 684*10598SGlenn.Barry@Sun.COM if (!aBuf) 685*10598SGlenn.Barry@Sun.COM return (GSS_S_FAILURE); 6860Sstevel@tonic-gate 687*10598SGlenn.Barry@Sun.COM if (addNullChar) 688*10598SGlenn.Barry@Sun.COM len = srcBuf->length + 1; 689*10598SGlenn.Barry@Sun.COM else 690*10598SGlenn.Barry@Sun.COM len = srcBuf->length; 6910Sstevel@tonic-gate 692*10598SGlenn.Barry@Sun.COM if (!(aBuf->value = (void*)malloc(len))) { 693*10598SGlenn.Barry@Sun.COM free(aBuf); 694*10598SGlenn.Barry@Sun.COM return (GSS_S_FAILURE); 695*10598SGlenn.Barry@Sun.COM } 6960Sstevel@tonic-gate 6970Sstevel@tonic-gate 698*10598SGlenn.Barry@Sun.COM (void) memcpy(aBuf->value, srcBuf->value, srcBuf->length); 699*10598SGlenn.Barry@Sun.COM aBuf->length = srcBuf->length; 700*10598SGlenn.Barry@Sun.COM *destBuf = aBuf; 7010Sstevel@tonic-gate 702*10598SGlenn.Barry@Sun.COM /* optionally add a NULL character */ 703*10598SGlenn.Barry@Sun.COM if (addNullChar) 704*10598SGlenn.Barry@Sun.COM ((char *)aBuf->value)[aBuf->length] = '\0'; 7050Sstevel@tonic-gate 706*10598SGlenn.Barry@Sun.COM return (GSS_S_COMPLETE); 707*10598SGlenn.Barry@Sun.COM } /* ****** gssint_create_copy_buffer ****** */ 708*10598SGlenn.Barry@Sun.COM 709