1 0 stevel /* 2 10598 Glenn * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 3 0 stevel * Use is subject to license terms. 4 0 stevel */ 5 0 stevel 6 10598 Glenn #include "mglueP.h" 7 0 stevel 8 0 stevel #include <stdio.h> 9 10598 Glenn #ifdef HAVE_STDLIB_H 10 0 stevel #include <stdlib.h> 11 10598 Glenn #endif 12 10598 Glenn #include <string.h> 13 0 stevel #include <errno.h> 14 0 stevel 15 10598 Glenn #include "k5-platform-store_32.h" 16 10598 Glenn #include "k5-platform-store_16.h" 17 10598 Glenn /* 18 10598 Glenn * SUNW17PACresync 19 10598 Glenn * MIT has diff names for these GSS utilities. Solaris needs to change 20 10598 Glenn * them globally to get in sync w/MIT. 21 10598 Glenn * Revisit for full 1.7 resync. 22 10598 Glenn */ 23 10598 Glenn #define gssint_get_modOptions __gss_get_modOptions 24 10598 Glenn #define gssint_der_length_size der_length_size 25 10598 Glenn #define gssint_get_der_length get_der_length 26 10598 Glenn #define gssint_put_der_length put_der_length 27 10598 Glenn #define gssint_get_mechanism __gss_get_mechanism 28 10598 Glenn #define gssint_get_mechanism_cred __gss_get_mechanism_cred 29 10598 Glenn #define gssint_copy_oid_set gss_copy_oid_set 30 10598 Glenn #define gssint_get_mech_type __gss_get_mech_type 31 10598 Glenn #define gssint_export_internal_name __gss_export_internal_name 32 10598 Glenn #define gssint_release_internal_name __gss_release_internal_name 33 10598 Glenn #define gssint_convert_name_to_union_name __gss_convert_name_to_union_name 34 10598 Glenn #define gssint_import_internal_name __gss_import_internal_name 35 10598 Glenn #define gssint_display_internal_name __gss_display_internal_name 36 10598 Glenn 37 10598 Glenn 38 0 stevel #define MSO_BIT (8*(sizeof (int) - 1)) /* Most significant octet bit */ 39 10598 Glenn 40 10598 Glenn extern gss_mechanism *gssint_mechs_array; 41 0 stevel 42 0 stevel /* 43 0 stevel * This file contains the support routines for the glue layer. 44 0 stevel */ 45 0 stevel 46 0 stevel /* 47 0 stevel * get_der_length: Givin a pointer to a buffer that contains a DER encoded 48 0 stevel * length, decode the length updating the buffer to point to the character 49 0 stevel * after the DER encoding. The parameter bytes will point to the number of 50 0 stevel * bytes that made up the DER encoding of the length originally pointed to 51 0 stevel * by the buffer. Note we return -1 on error. 52 0 stevel */ 53 0 stevel int 54 10598 Glenn gssint_get_der_length(unsigned char **buf, unsigned int buf_len, unsigned int *bytes) 55 0 stevel { 56 10598 Glenn /* p points to the beginning of the buffer */ 57 10598 Glenn unsigned char *p = *buf; 58 10598 Glenn int length, new_length; 59 10598 Glenn unsigned int octets; 60 0 stevel 61 10598 Glenn if (buf_len < 1) 62 10598 Glenn return (-1); 63 0 stevel 64 10598 Glenn /* We should have at least one byte */ 65 10598 Glenn *bytes = 1; 66 0 stevel 67 10598 Glenn /* 68 10598 Glenn * If the High order bit is not set then the length is just the value 69 10598 Glenn * of *p. 70 10598 Glenn */ 71 10598 Glenn if (*p < 128) { 72 10598 Glenn *buf = p+1; /* Advance the buffer */ 73 0 stevel return (*p); /* return the length */ 74 10598 Glenn } 75 0 stevel 76 10598 Glenn /* 77 10598 Glenn * if the High order bit is set, then the low order bits represent 78 10598 Glenn * the number of bytes that contain the DER encoding of the length. 79 10598 Glenn */ 80 0 stevel 81 10598 Glenn octets = *p++ & 0x7f; 82 10598 Glenn *bytes += octets; 83 0 stevel 84 10598 Glenn /* See if the supplied buffer contains enough bytes for the length. */ 85 10598 Glenn if (octets > buf_len - 1) 86 10598 Glenn return (-1); 87 0 stevel 88 10598 Glenn /* 89 10598 Glenn * Calculate a multibyte length. The length is encoded as an 90 10598 Glenn * unsigned integer base 256. 91 10598 Glenn */ 92 10598 Glenn for (length = 0; octets; octets--) { 93 10598 Glenn new_length = (length << 8) + *p++; 94 10598 Glenn if (new_length < length) /* overflow */ 95 10598 Glenn return (-1); 96 10598 Glenn length = new_length; 97 10598 Glenn } 98 0 stevel 99 10598 Glenn *buf = p; /* Advance the buffer */ 100 0 stevel 101 10598 Glenn return (length); 102 0 stevel } 103 0 stevel 104 0 stevel /* 105 0 stevel * der_length_size: Return the number of bytes to encode a given length. 106 0 stevel */ 107 0 stevel unsigned int 108 10598 Glenn gssint_der_length_size(unsigned int len) 109 0 stevel { 110 10598 Glenn int i; 111 0 stevel 112 10598 Glenn if (len < 128) 113 10598 Glenn return (1); 114 0 stevel 115 10598 Glenn for (i = 0; len; i++) { 116 10598 Glenn len >>= 8; 117 10598 Glenn } 118 0 stevel 119 10598 Glenn return (i+1); 120 0 stevel } 121 0 stevel 122 0 stevel /* 123 0 stevel * put_der_length: Encode the supplied length into the buffer pointed to 124 0 stevel * by buf. max_length represents the maximum length of the buffer pointed 125 0 stevel * to by buff. We will advance buf to point to the character after the newly 126 0 stevel * DER encoded length. We return 0 on success or -l it the length cannot 127 0 stevel * be encoded in max_len characters. 128 0 stevel */ 129 0 stevel int 130 10598 Glenn gssint_put_der_length(unsigned int length, unsigned char **buf, unsigned int max_len) 131 0 stevel { 132 10598 Glenn unsigned char *s, *p; 133 10598 Glenn unsigned int buf_len = 0; 134 10598 Glenn int i, first; 135 0 stevel 136 10598 Glenn /* Oops */ 137 10598 Glenn if (buf == 0 || max_len < 1) 138 10598 Glenn return (-1); 139 0 stevel 140 10598 Glenn s = *buf; 141 10598 Glenn 142 10598 Glenn /* Single byte is the length */ 143 10598 Glenn if (length < 128) { 144 10598 Glenn *s++ = length; 145 10598 Glenn *buf = s; 146 10598 Glenn return (0); 147 10598 Glenn } 148 10598 Glenn 149 10598 Glenn /* First byte contains the number of octets */ 150 10598 Glenn p = s + 1; 151 10598 Glenn 152 10598 Glenn /* Running total of the DER encoding length */ 153 10598 Glenn buf_len = 0; 154 10598 Glenn 155 10598 Glenn /* 156 10598 Glenn * Encode MSB first. We do the encoding by setting a shift 157 10598 Glenn * factor to MSO_BIT (24 for 32 bit words) and then shifting the length 158 10598 Glenn * by the factor. We then encode the resulting low order byte. 159 10598 Glenn * We subtract 8 from the shift factor and repeat to ecnode the next 160 10598 Glenn * byte. We stop when the shift factor is zero or we've run out of 161 10598 Glenn * buffer to encode into. 162 10598 Glenn */ 163 10598 Glenn first = 0; 164 10598 Glenn for (i = MSO_BIT; i >= 0 && buf_len <= max_len; i -= 8) { 165 10598 Glenn unsigned int v; 166 10598 Glenn v = (length >> i) & 0xff; 167 10598 Glenn if ((v) || first) { 168 10598 Glenn buf_len += 1; 169 10598 Glenn *p++ = v; 170 10598 Glenn first = 1; 171 0 stevel } 172 10598 Glenn } 173 10598 Glenn if (i >= 0) /* buffer overflow */ 174 10598 Glenn return (-1); 175 0 stevel 176 10598 Glenn /* 177 10598 Glenn * We go back now and set the first byte to be the length with 178 10598 Glenn * the high order bit set. 179 10598 Glenn */ 180 10598 Glenn *s = buf_len | 0x80; 181 10598 Glenn *buf = p; 182 0 stevel 183 10598 Glenn return (0); 184 0 stevel } 185 0 stevel 186 0 stevel 187 0 stevel /* 188 0 stevel * glue routine for get_mech_type 189 0 stevel * 190 0 stevel */ 191 10598 Glenn 192 10598 Glenn OM_uint32 gssint_get_mech_type_oid(OID, token) 193 10598 Glenn gss_OID OID; 194 10598 Glenn gss_buffer_t token; 195 0 stevel { 196 10598 Glenn unsigned char * buffer_ptr; 197 10598 Glenn int length; 198 10598 Glenn 199 10598 Glenn /* 200 10598 Glenn * This routine reads the prefix of "token" in order to determine 201 10598 Glenn * its mechanism type. It assumes the encoding suggested in 202 10598 Glenn * Appendix B of RFC 1508. This format starts out as follows : 203 10598 Glenn * 204 10598 Glenn * tag for APPLICATION 0, Sequence[constructed, definite length] 205 10598 Glenn * length of remainder of token 206 10598 Glenn * tag of OBJECT IDENTIFIER 207 10598 Glenn * length of mechanism OID 208 10598 Glenn * encoding of mechanism OID 209 10598 Glenn * <the rest of the token> 210 10598 Glenn * 211 10598 Glenn * Numerically, this looks like : 212 10598 Glenn * 213 10598 Glenn * 0x60 214 10598 Glenn * <length> - could be multiple bytes 215 10598 Glenn * 0x06 216 10598 Glenn * <length> - assume only one byte, hence OID length < 127 217 10598 Glenn * <mech OID bytes> 218 10598 Glenn * 219 10598 Glenn * The routine fills in the OID value and returns an error as necessary. 220 10598 Glenn */ 221 10598 Glenn 222 0 stevel if (OID == NULL) 223 0 stevel return (GSS_S_CALL_INACCESSIBLE_WRITE); 224 0 stevel 225 0 stevel if ((token == NULL) || (token->value == NULL)) 226 10598 Glenn return (GSS_S_DEFECTIVE_TOKEN); 227 10598 Glenn 228 10598 Glenn /* Skip past the APP/Sequnce byte and the token length */ 229 10598 Glenn 230 10598 Glenn buffer_ptr = (unsigned char *) token->value; 231 0 stevel 232 10598 Glenn if (*(buffer_ptr++) != 0x60) 233 10598 Glenn return (GSS_S_DEFECTIVE_TOKEN); 234 10598 Glenn length = *buffer_ptr++; 235 0 stevel 236 0 stevel /* check if token length is null */ 237 0 stevel if (length == 0) 238 0 stevel return (GSS_S_DEFECTIVE_TOKEN); 239 0 stevel 240 10598 Glenn if (length & 0x80) { 241 10598 Glenn if ((length & 0x7f) > 4) 242 10598 Glenn return (GSS_S_DEFECTIVE_TOKEN); 243 10598 Glenn buffer_ptr += length & 0x7f; 244 10598 Glenn } 245 10598 Glenn 246 10598 Glenn if (*(buffer_ptr++) != 0x06) 247 10598 Glenn return (GSS_S_DEFECTIVE_TOKEN); 248 10598 Glenn 249 10598 Glenn OID->length = (OM_uint32) *(buffer_ptr++); 250 10598 Glenn OID->elements = (void *) buffer_ptr; 251 10598 Glenn return (GSS_S_COMPLETE); 252 10598 Glenn } 253 0 stevel 254 10598 Glenn /* 255 10598 Glenn * The following mechanisms do not always identify themselves 256 10598 Glenn * per the GSS-API specification, when interoperating with MS 257 10598 Glenn * peers. We include the OIDs here so we do not have to link 258 10598 Glenn * with the mechanism. 259 10598 Glenn */ 260 10598 Glenn static gss_OID_desc gss_ntlm_mechanism_oid_desc = 261 10598 Glenn {10, (void *)"\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"}; 262 10598 Glenn static gss_OID_desc gss_spnego_mechanism_oid_desc = 263 10598 Glenn {6, (void *)"\x2b\x06\x01\x05\x05\x02"}; 264 10598 Glenn static gss_OID_desc gss_krb5_mechanism_oid_desc = 265 10598 Glenn {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"}; 266 0 stevel 267 10598 Glenn #define NTLMSSP_SIGNATURE "NTLMSSP" 268 10598 Glenn 269 10598 Glenn OM_uint32 gssint_get_mech_type(OID, token) 270 10598 Glenn gss_OID OID; 271 10598 Glenn gss_buffer_t token; 272 10598 Glenn { 273 10598 Glenn /* Check for interoperability exceptions */ 274 10598 Glenn if (token->length >= sizeof(NTLMSSP_SIGNATURE) && 275 10598 Glenn memcmp(token->value, NTLMSSP_SIGNATURE, 276 10598 Glenn sizeof(NTLMSSP_SIGNATURE)) == 0) { 277 10598 Glenn *OID = gss_ntlm_mechanism_oid_desc; 278 10598 Glenn } else if (token->length != 0 && 279 10598 Glenn ((char *)token->value)[0] == 0x6E) { 280 10598 Glenn /* Could be a raw AP-REQ (check for APPLICATION tag) */ 281 10598 Glenn *OID = gss_krb5_mechanism_oid_desc; 282 10598 Glenn } else if (token->length == 0) { 283 10598 Glenn *OID = gss_spnego_mechanism_oid_desc; 284 10598 Glenn } else { 285 10598 Glenn return gssint_get_mech_type_oid(OID, token); 286 10598 Glenn } 287 10598 Glenn 288 10598 Glenn return (GSS_S_COMPLETE); 289 0 stevel } 290 0 stevel 291 0 stevel 292 0 stevel /* 293 0 stevel * Internal routines to get and release an internal mechanism name 294 0 stevel */ 295 10598 Glenn 296 10598 Glenn #if 0 /* SUNW17PACresync */ 297 10598 Glenn #include "mglueP.h" 298 10598 Glenn #endif 299 10598 Glenn 300 10598 Glenn OM_uint32 gssint_import_internal_name (minor_status, mech_type, union_name, 301 10598 Glenn internal_name) 302 0 stevel OM_uint32 *minor_status; 303 10598 Glenn gss_OID mech_type; 304 0 stevel gss_union_name_t union_name; 305 0 stevel gss_name_t *internal_name; 306 0 stevel { 307 10598 Glenn OM_uint32 status; 308 10598 Glenn gss_mechanism mech; 309 0 stevel 310 10598 Glenn mech = gssint_get_mechanism (mech_type); 311 10598 Glenn if (mech) { 312 10598 Glenn if (mech->gss_import_name) { 313 10598 Glenn status = mech->gss_import_name ( 314 10598 Glenn mech->context, /* SUNW17PACresync */ 315 10598 Glenn minor_status, 316 10598 Glenn union_name->external_name, 317 10598 Glenn union_name->name_type, 318 10598 Glenn internal_name); 319 10598 Glenn if (status != GSS_S_COMPLETE) 320 10598 Glenn map_error(minor_status, mech); 321 10598 Glenn } else 322 10598 Glenn status = GSS_S_UNAVAILABLE; 323 0 stevel 324 10598 Glenn return (status); 325 10598 Glenn } 326 0 stevel 327 10598 Glenn return (GSS_S_BAD_MECH); 328 0 stevel } 329 0 stevel 330 10598 Glenn OM_uint32 gssint_export_internal_name(minor_status, mech_type, 331 10598 Glenn internal_name, name_buf) 332 10598 Glenn OM_uint32 *minor_status; 333 10598 Glenn const gss_OID mech_type; 334 10598 Glenn const gss_name_t internal_name; 335 10598 Glenn gss_buffer_t name_buf; 336 10598 Glenn { 337 10598 Glenn OM_uint32 status; 338 10598 Glenn gss_mechanism mech; 339 10598 Glenn gss_buffer_desc dispName; 340 10598 Glenn gss_OID nameOid; 341 10598 Glenn unsigned char *buf = NULL; 342 10598 Glenn const unsigned char tokId[] = "\x04\x01"; 343 10598 Glenn const unsigned int tokIdLen = 2; 344 10598 Glenn const int mechOidLenLen = 2, mechOidTagLen = 1, nameLenLen = 4; 345 10598 Glenn int mechOidDERLen = 0; 346 10598 Glenn int mechOidLen = 0; 347 0 stevel 348 10598 Glenn mech = gssint_get_mechanism(mech_type); 349 10598 Glenn if (!mech) 350 10598 Glenn return (GSS_S_BAD_MECH); 351 10598 Glenn 352 10598 Glenn if (mech->gss_export_name) { 353 10598 Glenn status = mech->gss_export_name( 354 10598 Glenn mech->context, /* SUNW17PACresync */ 355 10598 Glenn minor_status, 356 10598 Glenn internal_name, 357 10598 Glenn name_buf); 358 10598 Glenn if (status != GSS_S_COMPLETE) 359 10598 Glenn map_error(minor_status, mech); 360 10598 Glenn return status; 361 10598 Glenn } 362 10598 Glenn 363 10598 Glenn /* 364 10598 Glenn * if we are here it is because the mechanism does not provide 365 10598 Glenn * a gss_export_name so we will use our implementation. We 366 10598 Glenn * do required that the mechanism define a gss_display_name. 367 10598 Glenn */ 368 10598 Glenn if (!mech->gss_display_name) 369 10598 Glenn return (GSS_S_UNAVAILABLE); 370 10598 Glenn 371 10598 Glenn /* 372 10598 Glenn * NOTE: RFC2743 (section 3.2) governs the format of the outer 373 10598 Glenn * wrapper of exported names; the mechanisms' specs govern 374 10598 Glenn * the format of the inner portion of the exported name 375 10598 Glenn * and, for some (e.g., RFC1964, the Kerberos V mech), a 376 10598 Glenn * generic default as implemented here will do. 377 10598 Glenn * 378 10598 Glenn * The outer wrapper of an exported MN is: 2-octet tok Id 379 10598 Glenn * (0x0401) + 2-octet network-byte order mech OID length + mech 380 10598 Glenn * oid (in DER format, including DER tag and DER length) + 381 10598 Glenn * 4-octet network-byte order length of inner portion + inner 382 10598 Glenn * portion. 383 10598 Glenn * 384 10598 Glenn * For the Kerberos V mechanism the inner portion of an exported 385 10598 Glenn * MN is the display name string and ignores the name type OID 386 10598 Glenn * altogether. And we hope this will be so for any future 387 10598 Glenn * mechanisms also, so that factoring name export/import out of 388 10598 Glenn * the mech and into libgss pays off. 389 10598 Glenn */ 390 10598 Glenn if ((status = mech->gss_display_name( 391 10598 Glenn mech->context, 392 10598 Glenn minor_status, 393 10598 Glenn internal_name, 394 10598 Glenn &dispName, 395 10598 Glenn &nameOid)) 396 10598 Glenn != GSS_S_COMPLETE) { 397 10598 Glenn map_error(minor_status, mech); 398 10598 Glenn return (status); 399 10598 Glenn } 400 10598 Glenn 401 10598 Glenn /* determine the size of the buffer needed */ 402 10598 Glenn mechOidDERLen = gssint_der_length_size(mech_type->length); 403 10598 Glenn name_buf->length = tokIdLen + mechOidLenLen + 404 10598 Glenn mechOidTagLen + mechOidDERLen + 405 10598 Glenn mech_type->length + 406 10598 Glenn nameLenLen + dispName.length; 407 10598 Glenn if ((name_buf->value = (void*)malloc(name_buf->length)) == 408 10598 Glenn (void*)NULL) { 409 10598 Glenn name_buf->length = 0; 410 10598 Glenn (void) gss_release_buffer(&status, &dispName); 411 10598 Glenn return (GSS_S_FAILURE); 412 10598 Glenn } 413 10598 Glenn 414 10598 Glenn /* now create the name ..... */ 415 10598 Glenn buf = (unsigned char *)name_buf->value; 416 10598 Glenn (void) memset(name_buf->value, 0, name_buf->length); 417 10598 Glenn (void) memcpy(buf, tokId, tokIdLen); 418 10598 Glenn buf += tokIdLen; 419 10598 Glenn 420 10598 Glenn /* spec allows only 2 bytes for the mech oid length */ 421 10598 Glenn mechOidLen = mechOidDERLen + mechOidTagLen + mech_type->length; 422 10598 Glenn store_16_be(mechOidLen, buf); 423 10598 Glenn buf += 2; 424 10598 Glenn 425 10598 Glenn /* 426 10598 Glenn * DER Encoding of mech OID contains OID Tag (0x06), length and 427 10598 Glenn * mech OID value 428 10598 Glenn */ 429 10598 Glenn *buf++ = 0x06; 430 10598 Glenn if (gssint_put_der_length(mech_type->length, &buf, 431 10598 Glenn (name_buf->length - tokIdLen -2)) != 0) { 432 10598 Glenn name_buf->length = 0; 433 10598 Glenn free(name_buf->value); 434 10598 Glenn (void) gss_release_buffer(&status, &dispName); 435 10598 Glenn return (GSS_S_FAILURE); 436 10598 Glenn } 437 10598 Glenn 438 10598 Glenn (void) memcpy(buf, mech_type->elements, mech_type->length); 439 10598 Glenn buf += mech_type->length; 440 10598 Glenn 441 10598 Glenn /* spec designates the next 4 bytes for the name length */ 442 10598 Glenn store_32_be(dispName.length, buf); 443 10598 Glenn buf += 4; 444 10598 Glenn 445 10598 Glenn /* for the final ingredient - add the name from gss_display_name */ 446 10598 Glenn (void) memcpy(buf, dispName.value, dispName.length); 447 10598 Glenn 448 10598 Glenn /* release the buffer obtained from gss_display_name */ 449 10598 Glenn (void) gss_release_buffer(minor_status, &dispName); 450 10598 Glenn return (GSS_S_COMPLETE); 451 10598 Glenn } /* gssint_export_internal_name */ 452 10598 Glenn 453 10598 Glenn OM_uint32 gssint_display_internal_name (minor_status, mech_type, internal_name, 454 10598 Glenn external_name, name_type) 455 10598 Glenn OM_uint32 *minor_status; 456 10598 Glenn gss_OID mech_type; 457 10598 Glenn gss_name_t internal_name; 458 10598 Glenn gss_buffer_t external_name; 459 10598 Glenn gss_OID *name_type; 460 0 stevel { 461 10598 Glenn OM_uint32 status; 462 10598 Glenn gss_mechanism mech; 463 0 stevel 464 10598 Glenn mech = gssint_get_mechanism (mech_type); 465 10598 Glenn if (mech) { 466 10598 Glenn if (mech->gss_display_name) { 467 10598 Glenn status = mech->gss_display_name ( 468 10598 Glenn mech->context, 469 10598 Glenn minor_status, 470 10598 Glenn internal_name, 471 10598 Glenn external_name, 472 10598 Glenn name_type); 473 10598 Glenn if (status != GSS_S_COMPLETE) 474 10598 Glenn map_error(minor_status, mech); 475 10598 Glenn } else 476 10598 Glenn status = GSS_S_UNAVAILABLE; 477 0 stevel 478 10598 Glenn return (status); 479 10598 Glenn } 480 0 stevel 481 10598 Glenn return (GSS_S_BAD_MECH); 482 0 stevel } 483 0 stevel 484 10598 Glenn OM_uint32 gssint_release_internal_name (minor_status, mech_type, internal_name) 485 10598 Glenn OM_uint32 *minor_status; 486 10598 Glenn gss_OID mech_type; 487 10598 Glenn gss_name_t *internal_name; 488 0 stevel { 489 10598 Glenn OM_uint32 status; 490 10598 Glenn gss_mechanism mech; 491 0 stevel 492 10598 Glenn mech = gssint_get_mechanism (mech_type); 493 10598 Glenn if (mech) { 494 10598 Glenn if (mech->gss_release_name) { 495 10598 Glenn status = mech->gss_release_name ( 496 10598 Glenn mech->context, 497 10598 Glenn minor_status, 498 10598 Glenn internal_name); 499 10598 Glenn if (status != GSS_S_COMPLETE) 500 10598 Glenn map_error(minor_status, mech); 501 10598 Glenn } else 502 10598 Glenn status = GSS_S_UNAVAILABLE; 503 0 stevel 504 10598 Glenn return (status); 505 10598 Glenn } 506 0 stevel 507 10598 Glenn return (GSS_S_BAD_MECH); 508 0 stevel } 509 0 stevel 510 10598 Glenn OM_uint32 gssint_delete_internal_sec_context (minor_status, 511 10598 Glenn mech_type, 512 10598 Glenn internal_ctx, 513 10598 Glenn output_token) 514 10598 Glenn OM_uint32 *minor_status; 515 10598 Glenn gss_OID mech_type; 516 10598 Glenn gss_ctx_id_t *internal_ctx; 517 10598 Glenn gss_buffer_t output_token; 518 10598 Glenn { 519 10598 Glenn OM_uint32 status; 520 10598 Glenn gss_mechanism mech; 521 10598 Glenn 522 10598 Glenn mech = gssint_get_mechanism (mech_type); 523 10598 Glenn if (mech) { 524 10598 Glenn if (mech->gss_delete_sec_context) 525 10598 Glenn status = mech->gss_delete_sec_context ( 526 10598 Glenn mech->context, /* SUNW17PACresync */ 527 10598 Glenn minor_status, 528 10598 Glenn internal_ctx, 529 10598 Glenn output_token); 530 10598 Glenn else 531 10598 Glenn /* SUNW17PACresync - map error here? */ 532 10598 Glenn status = GSS_S_UNAVAILABLE; 533 10598 Glenn 534 10598 Glenn return (status); 535 10598 Glenn } 536 10598 Glenn 537 10598 Glenn return (GSS_S_BAD_MECH); 538 10598 Glenn } 539 0 stevel 540 0 stevel /* 541 0 stevel * This function converts an internal gssapi name to a union gssapi 542 0 stevel * name. Note that internal_name should be considered "consumed" by 543 0 stevel * this call, whether or not we return an error. 544 0 stevel */ 545 10598 Glenn OM_uint32 gssint_convert_name_to_union_name(minor_status, mech, 546 10598 Glenn internal_name, external_name) 547 10598 Glenn OM_uint32 *minor_status; 548 10598 Glenn gss_mechanism mech; 549 10598 Glenn gss_name_t internal_name; 550 10598 Glenn gss_name_t *external_name; 551 0 stevel { 552 10598 Glenn OM_uint32 major_status,tmp; 553 10598 Glenn gss_union_name_t union_name; 554 0 stevel 555 10598 Glenn union_name = (gss_union_name_t) malloc (sizeof(gss_union_name_desc)); 556 10598 Glenn if (!union_name) { 557 10598 Glenn major_status = GSS_S_FAILURE; 558 10598 Glenn *minor_status = ENOMEM; 559 10598 Glenn map_errcode(minor_status); 560 10598 Glenn goto allocation_failure; 561 10598 Glenn } 562 10598 Glenn union_name->mech_type = 0; 563 10598 Glenn union_name->mech_name = internal_name; 564 10598 Glenn union_name->name_type = 0; 565 10598 Glenn union_name->external_name = 0; 566 0 stevel 567 10598 Glenn major_status = generic_gss_copy_oid(minor_status, &mech->mech_type, 568 10598 Glenn &union_name->mech_type); 569 10598 Glenn if (major_status != GSS_S_COMPLETE) { 570 10598 Glenn map_errcode(minor_status); 571 10598 Glenn goto allocation_failure; 572 10598 Glenn } 573 0 stevel 574 10598 Glenn union_name->external_name = 575 10598 Glenn (gss_buffer_t) malloc(sizeof(gss_buffer_desc)); 576 10598 Glenn if (!union_name->external_name) { 577 10598 Glenn major_status = GSS_S_FAILURE; 578 10598 Glenn *minor_status = ENOMEM; 579 10598 Glenn goto allocation_failure; 580 10598 Glenn } 581 10598 Glenn 582 10598 Glenn major_status = mech->gss_display_name( 583 10598 Glenn mech->context, /* SUNW17PACresync */ 584 10598 Glenn minor_status, 585 10598 Glenn internal_name, 586 10598 Glenn union_name->external_name, 587 10598 Glenn &union_name->name_type); 588 10598 Glenn if (major_status != GSS_S_COMPLETE) { 589 10598 Glenn map_error(minor_status, mech); 590 10598 Glenn goto allocation_failure; 591 10598 Glenn } 592 0 stevel 593 10598 Glenn union_name->loopback = union_name; 594 10598 Glenn *external_name = (gss_name_t) union_name; 595 10598 Glenn return (GSS_S_COMPLETE); 596 0 stevel 597 0 stevel allocation_failure: 598 10598 Glenn if (union_name) { 599 10598 Glenn if (union_name->external_name) { 600 10598 Glenn if (union_name->external_name->value) 601 10598 Glenn free(union_name->external_name->value); 602 10598 Glenn free(union_name->external_name); 603 0 stevel } 604 10598 Glenn if (union_name->name_type) 605 10598 Glenn (void) gss_release_oid(&tmp, &union_name->name_type); 606 10598 Glenn if (union_name->mech_type) 607 10598 Glenn (void) gss_release_oid(&tmp, &union_name->mech_type); 608 10598 Glenn free(union_name); 609 10598 Glenn } 610 10598 Glenn /* 611 10598 Glenn * do as the top comment says - since we are now owners of 612 10598 Glenn * internal_name, we must clean it up 613 10598 Glenn */ 614 10598 Glenn if (internal_name) 615 10598 Glenn (void) gssint_release_internal_name(&tmp, &mech->mech_type, 616 10598 Glenn &internal_name); 617 10598 Glenn return (major_status); 618 0 stevel } 619 0 stevel 620 0 stevel /* 621 0 stevel * Glue routine for returning the mechanism-specific credential from a 622 0 stevel * external union credential. 623 0 stevel */ 624 0 stevel gss_cred_id_t 625 10598 Glenn gssint_get_mechanism_cred(union_cred, mech_type) 626 10598 Glenn gss_union_cred_t union_cred; 627 10598 Glenn gss_OID mech_type; 628 0 stevel { 629 10598 Glenn int i; 630 0 stevel 631 10598 Glenn if (union_cred == (gss_union_cred_t) GSS_C_NO_CREDENTIAL) 632 10598 Glenn return GSS_C_NO_CREDENTIAL; 633 0 stevel 634 10598 Glenn /* 635 10598 Glenn * SUNW17PACresync 636 10598 Glenn * Disable this block as it causes problems for gss_add_cred 637 10598 Glenn * for HTTP SSO (and also probably causes STC gss.13 to fail too). 638 10598 Glenn */ 639 10598 Glenn #if 0 640 10598 Glenn /* SPNEGO mechanism will again call into GSSAPI */ 641 10598 Glenn if (g_OID_equal(&gss_spnego_mechanism_oid_desc, mech_type)) 642 10598 Glenn return (gss_cred_id_t)union_cred; 643 10598 Glenn #endif 644 10598 Glenn 645 10598 Glenn for (i=0; i < union_cred->count; i++) { 646 10598 Glenn if (g_OID_equal(mech_type, &union_cred->mechs_array[i])) 647 10598 Glenn return union_cred->cred_array[i]; 648 10598 Glenn 649 10598 Glenn /* for SPNEGO, check the next-lower set of creds */ 650 10598 Glenn if (g_OID_equal(&gss_spnego_mechanism_oid_desc, &union_cred->mechs_array[i])) { 651 10598 Glenn gss_union_cred_t candidate_cred; 652 10598 Glenn gss_cred_id_t sub_cred; 653 10598 Glenn 654 10598 Glenn candidate_cred = (gss_union_cred_t)union_cred->cred_array[i]; 655 10598 Glenn sub_cred = gssint_get_mechanism_cred(candidate_cred, mech_type); 656 10598 Glenn 657 10598 Glenn if(sub_cred != GSS_C_NO_CREDENTIAL) 658 10598 Glenn return sub_cred; 659 0 stevel } 660 10598 Glenn } 661 10598 Glenn 662 10598 Glenn return GSS_C_NO_CREDENTIAL; 663 0 stevel } 664 0 stevel 665 0 stevel /* 666 0 stevel * Routine to create and copy the gss_buffer_desc structure. 667 0 stevel * Both space for the structure and the data is allocated. 668 0 stevel */ 669 0 stevel OM_uint32 670 5053 gtb gssint_create_copy_buffer(srcBuf, destBuf, addNullChar) 671 10598 Glenn const gss_buffer_t srcBuf; 672 10598 Glenn gss_buffer_t *destBuf; 673 10598 Glenn int addNullChar; 674 0 stevel { 675 10598 Glenn gss_buffer_t aBuf; 676 10598 Glenn unsigned int len; 677 0 stevel 678 10598 Glenn if (destBuf == NULL) 679 10598 Glenn return (GSS_S_CALL_INACCESSIBLE_WRITE); 680 0 stevel 681 10598 Glenn *destBuf = 0; 682 0 stevel 683 10598 Glenn aBuf = (gss_buffer_t)malloc(sizeof (gss_buffer_desc)); 684 10598 Glenn if (!aBuf) 685 10598 Glenn return (GSS_S_FAILURE); 686 0 stevel 687 10598 Glenn if (addNullChar) 688 10598 Glenn len = srcBuf->length + 1; 689 10598 Glenn else 690 10598 Glenn len = srcBuf->length; 691 0 stevel 692 10598 Glenn if (!(aBuf->value = (void*)malloc(len))) { 693 10598 Glenn free(aBuf); 694 10598 Glenn return (GSS_S_FAILURE); 695 10598 Glenn } 696 0 stevel 697 0 stevel 698 10598 Glenn (void) memcpy(aBuf->value, srcBuf->value, srcBuf->length); 699 10598 Glenn aBuf->length = srcBuf->length; 700 10598 Glenn *destBuf = aBuf; 701 0 stevel 702 10598 Glenn /* optionally add a NULL character */ 703 10598 Glenn if (addNullChar) 704 10598 Glenn ((char *)aBuf->value)[aBuf->length] = '\0'; 705 0 stevel 706 10598 Glenn return (GSS_S_COMPLETE); 707 10598 Glenn } /* ****** gssint_create_copy_buffer ****** */ 708 10598 Glenn 709