1 // Copyright (C) 2002 Microsoft Corporation 2 // All rights reserved. 3 // 4 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" 5 // WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 6 // OR IMPLIED, INCLUDING BUT NOT LIMITED 7 // TO THE IMPLIED WARRANTIES OF MERCHANTIBILITY 8 // AND/OR FITNESS FOR A PARTICULAR PURPOSE. 9 // 10 // Date - 10/08/2002 11 // Author - Sanj Surati 12 13 ///////////////////////////////////////////////////////////// 14 // 15 // SPNEGO.C 16 // 17 // SPNEGO Token Handler Source File 18 // 19 // Contains implementation of SPNEGO Token Handling API 20 // as defined in SPNEGO.H. 21 // 22 ///////////////////////////////////////////////////////////// 23 24 #pragma ident "%Z%%M% %I% %E% SMI" 25 26 #include <stdlib.h> 27 #include <stdio.h> 28 #include <memory.h> 29 #include "spnego.h" 30 #include "derparse.h" 31 #include "spnegoparse.h" 32 33 // 34 // Defined in DERPARSE.C 35 // 36 37 extern MECH_OID g_stcMechOIDList []; 38 39 40 /**********************************************************************/ 41 /** **/ 42 /** **/ 43 /** **/ 44 /** **/ 45 /** SPNEGO Token Handler API implementation **/ 46 /** **/ 47 /** **/ 48 /** **/ 49 /** **/ 50 /**********************************************************************/ 51 52 53 ///////////////////////////////////////////////////////////////////////////// 54 // 55 // Function: 56 // spnegoInitFromBinary 57 // 58 // Parameters: 59 // [in] pbTokenData - Binary Token Data 60 // [in] ulLength - Length of binary Token Data 61 // [out] phSpnegoToken - SPNEGO_TOKEN_HANDLE pointer 62 // 63 // Returns: 64 // int Success - SPNEGO_E_SUCCESS 65 // Failure - SPNEGO API Error code 66 // 67 // Comments : 68 // Initializes a SPNEGO_TOKEN_HANDLE from the supplied 69 // binary data. Data is copied locally. Returned data structure 70 // must be freed by calling spnegoFreeData(). 71 // 72 //////////////////////////////////////////////////////////////////////////// 73 74 int spnegoInitFromBinary( unsigned char* pbTokenData, unsigned long ulLength, SPNEGO_TOKEN_HANDLE* phSpnegoToken ) 75 { 76 int nReturn = SPNEGO_E_INVALID_PARAMETER; 77 SPNEGO_TOKEN** ppSpnegoToken = (SPNEGO_TOKEN**) phSpnegoToken; 78 79 // Pass off to a handler function that allows tighter control over how the token structure 80 // is handled. In this case, we want the token data copied and we want the associated buffer 81 // freed. 82 nReturn = InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYDATA, 83 SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA, pbTokenData, 84 ulLength, ppSpnegoToken ); 85 86 return nReturn; 87 } 88 89 ///////////////////////////////////////////////////////////////////////////// 90 // 91 // Function: 92 // spnegoCreateNegTokenInit 93 // 94 // Parameters: 95 // [in] MechType - MechType to specify in MechTypeList element 96 // [in] ucContextFlags - Context Flags element value 97 // [in] pbMechToken - Pointer to binary MechToken Data 98 // [in] ulMechTokenLen - Length of MechToken Data 99 // [in] pbMechListMIC - Pointer to binary MechListMIC Data 100 // [in] ulMechListMICLen - Length of MechListMIC Data 101 // [out] phSpnegoToken - SPNEGO_TOKEN_HANDLE pointer 102 // 103 // Returns: 104 // int Success - SPNEGO_E_SUCCESS 105 // Failure - SPNEGO API Error code 106 // 107 // Comments : 108 // Initializes a SPNEGO_TOKEN_HANDLE for a NegTokenInit type 109 // from the supplied parameters. ucContextFlags may be 0 or must be 110 // a valid flag combination. MechToken data can be NULL - if not, it 111 // must correspond to the MechType. MechListMIC can also be NULL. 112 // Returned data structure must be freed by calling spnegoFreeData(). 113 // 114 //////////////////////////////////////////////////////////////////////////// 115 116 int spnegoCreateNegTokenInit( SPNEGO_MECH_OID MechType, 117 unsigned char ucContextFlags, unsigned char* pbMechToken, 118 unsigned long ulMechTokenLen, unsigned char* pbMechListMIC, 119 unsigned long ulMechListMICLen, SPNEGO_TOKEN_HANDLE* phSpnegoToken ) 120 { 121 int nReturn = SPNEGO_E_INVALID_PARAMETER; 122 long nTokenLength = 0L; 123 long nInternalTokenLength = 0L; 124 unsigned char* pbTokenData = NULL; 125 SPNEGO_TOKEN** ppSpnegoToken = (SPNEGO_TOKEN**) phSpnegoToken; 126 127 if ( NULL != ppSpnegoToken && 128 IsValidMechOid( MechType ) && 129 IsValidContextFlags( ucContextFlags ) ) 130 { 131 // Get the actual token size 132 133 if ( ( nReturn = CalculateMinSpnegoInitTokenSize( ulMechTokenLen, ulMechListMICLen, 134 MechType, ( ucContextFlags != 0L ), 135 &nTokenLength, &nInternalTokenLength ) ) 136 == SPNEGO_E_SUCCESS ) 137 { 138 // Allocate a buffer to hold the data. 139 pbTokenData = calloc( 1, nTokenLength ); 140 141 if ( NULL != pbTokenData ) 142 { 143 144 // Now write the token 145 if ( ( nReturn = CreateSpnegoInitToken( MechType, 146 ucContextFlags, pbMechToken, 147 ulMechTokenLen, pbMechListMIC, 148 ulMechListMICLen, pbTokenData, 149 nTokenLength, nInternalTokenLength ) ) 150 == SPNEGO_E_SUCCESS ) 151 { 152 153 // This will copy our allocated pointer, and ensure that the sructure cleans 154 // up the data later 155 nReturn = InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYPTR, 156 SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA, 157 pbTokenData, nTokenLength, ppSpnegoToken ); 158 159 } 160 161 // Cleanup on failure 162 if ( SPNEGO_E_SUCCESS != nReturn ) 163 { 164 free( pbTokenData ); 165 } 166 167 } // IF alloc succeeded 168 else 169 { 170 nReturn = SPNEGO_E_OUT_OF_MEMORY; 171 } 172 173 } // If calculated token size 174 175 } // IF Valid Parameters 176 177 return nReturn; 178 } 179 180 ///////////////////////////////////////////////////////////////////////////// 181 // 182 // Function: 183 // spnegoCreateNegTokenTarg 184 // 185 // Parameters: 186 // [in] MechType - MechType to specify in supported MechType element 187 // [in] spnegoNegResult - NegResult value 188 // [in] pbMechToken - Pointer to response MechToken Data 189 // [in] ulMechTokenLen - Length of MechToken Data 190 // [in] pbMechListMIC - Pointer to binary MechListMIC Data 191 // [in] ulMechListMICLen - Length of MechListMIC Data 192 // [out] phSpnegoToken - SPNEGO_TOKEN_HANDLE pointer 193 // 194 // Returns: 195 // int Success - SPNEGO_E_SUCCESS 196 // Failure - SPNEGO API Error code 197 // 198 // Comments : 199 // Initializes a SPNEGO_TOKEN_HANDLE for a NegTokenTarg type 200 // from the supplied parameters. MechToken data can be NULL - if not, 201 // it must correspond to the MechType. MechListMIC can also be NULL. 202 // Returned data structure must be freed by calling spnegoFreeData(). 203 // 204 //////////////////////////////////////////////////////////////////////////// 205 206 int spnegoCreateNegTokenTarg( SPNEGO_MECH_OID MechType, 207 SPNEGO_NEGRESULT spnegoNegResult, unsigned char* pbMechToken, 208 unsigned long ulMechTokenLen, unsigned char* pbMechListMIC, 209 unsigned long ulMechListMICLen, SPNEGO_TOKEN_HANDLE* phSpnegoToken ) 210 { 211 int nReturn = SPNEGO_E_INVALID_PARAMETER; 212 long nTokenLength = 0L; 213 long nInternalTokenLength = 0L; 214 unsigned char* pbTokenData = NULL; 215 SPNEGO_TOKEN** ppSpnegoToken = (SPNEGO_TOKEN**) phSpnegoToken; 216 217 // 218 // spnego_mech_oid_NotUsed and spnego_negresult_NotUsed 219 // are okay here, however a valid MechOid is required 220 // if spnego_negresult_success or spnego_negresult_incomplete 221 // is specified. 222 // 223 224 if ( NULL != ppSpnegoToken && 225 226 ( IsValidMechOid( MechType ) || 227 spnego_mech_oid_NotUsed == MechType ) && 228 229 ( IsValidNegResult( spnegoNegResult ) || 230 spnego_negresult_NotUsed == spnegoNegResult ) && 231 232 !( !IsValidMechOid( MechType ) && 233 ( spnego_negresult_success == spnegoNegResult || 234 spnego_negresult_incomplete == spnegoNegResult ) ) ) 235 { 236 237 // Get the actual token size 238 239 if ( ( nReturn = CalculateMinSpnegoTargTokenSize( MechType, spnegoNegResult, ulMechTokenLen, 240 ulMechListMICLen, &nTokenLength, 241 &nInternalTokenLength ) ) 242 == SPNEGO_E_SUCCESS ) 243 { 244 // Allocate a buffer to hold the data. 245 pbTokenData = calloc( 1, nTokenLength ); 246 247 if ( NULL != pbTokenData ) 248 { 249 250 // Now write the token 251 if ( ( nReturn = CreateSpnegoTargToken( MechType, 252 spnegoNegResult, pbMechToken, 253 ulMechTokenLen, pbMechListMIC, 254 ulMechListMICLen, pbTokenData, 255 nTokenLength, nInternalTokenLength ) ) 256 == SPNEGO_E_SUCCESS ) 257 { 258 259 // This will copy our allocated pointer, and ensure that the sructure cleans 260 // up the data later 261 nReturn = InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYPTR, 262 SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA, 263 pbTokenData, nTokenLength, ppSpnegoToken ); 264 265 } 266 267 // Cleanup on failure 268 if ( SPNEGO_E_SUCCESS != nReturn ) 269 { 270 free( pbTokenData ); 271 } 272 273 } // IF alloc succeeded 274 else 275 { 276 nReturn = SPNEGO_E_OUT_OF_MEMORY; 277 } 278 279 } // If calculated token size 280 281 } // IF Valid Parameters 282 283 return nReturn; 284 } 285 286 ///////////////////////////////////////////////////////////////////////////// 287 // 288 // Function: 289 // spnegoTokenGetBinary 290 // 291 // Parameters: 292 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE 293 // [out] pbTokenData - Buffer to copy token into 294 // [in/out] pulDataLen - Length of pbTokenData buffer, filled out 295 // with actual size used upon function return. 296 // 297 // Returns: 298 // int Success - SPNEGO_E_SUCCESS 299 // Failure - SPNEGO API Error code 300 // 301 // Comments : 302 // Copies binary SPNEGO token data from hSpnegoToken into the user 303 // supplied buffer. If pbTokenData is NULL, or the value in pulDataLen 304 // is too small, the function will return SPNEGO_E_BUFFER_TOO_SMALL and 305 // fill out pulDataLen with the minimum required buffer size. 306 // 307 //////////////////////////////////////////////////////////////////////////// 308 309 int spnegoTokenGetBinary( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pbTokenData, 310 unsigned long * pulDataLen ) 311 { 312 int nReturn = SPNEGO_E_INVALID_PARAMETER; 313 SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken; 314 315 // Check parameters - pbTokenData is optional 316 if ( IsValidSpnegoToken( pSpnegoToken ) && 317 NULL != pulDataLen ) 318 { 319 320 // Check for Buffer too small conditions 321 if ( NULL == pbTokenData || 322 pSpnegoToken->ulBinaryDataLen > *pulDataLen ) 323 { 324 *pulDataLen = pSpnegoToken->ulBinaryDataLen; 325 nReturn = SPNEGO_E_BUFFER_TOO_SMALL; 326 } 327 else 328 { 329 memcpy( pbTokenData, pSpnegoToken->pbBinaryData, pSpnegoToken->ulBinaryDataLen ); 330 *pulDataLen = pSpnegoToken->ulBinaryDataLen; 331 nReturn = SPNEGO_E_SUCCESS; 332 } 333 334 } // IF parameters OK 335 336 return nReturn;; 337 } 338 339 ///////////////////////////////////////////////////////////////////////////// 340 // 341 // Function: 342 // spnegoFreeData 343 // 344 // Parameters: 345 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE 346 // 347 // Returns: 348 // void 349 // 350 // Comments : 351 // Frees up resources consumed by hSpnegoToken. The supplied data 352 // pointer is invalidated by this function. 353 // 354 //////////////////////////////////////////////////////////////////////////// 355 356 void spnegoFreeData( SPNEGO_TOKEN_HANDLE hSpnegoToken ) 357 { 358 FreeSpnegoToken( (SPNEGO_TOKEN*) hSpnegoToken); 359 return; 360 } 361 362 ///////////////////////////////////////////////////////////////////////////// 363 // 364 // Function: 365 // spnegoGetTokenType 366 // 367 // Parameters: 368 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE 369 // [out] piTokenType - Filled out with token type value. 370 // 371 // Returns: 372 // int Success - SPNEGO_E_SUCCESS 373 // Failure - SPNEGO API Error code 374 // 375 // Comments : 376 // The function will analyze hSpnegoToken and return the appropriate 377 // type in piTokenType. 378 // 379 //////////////////////////////////////////////////////////////////////////// 380 381 int spnegoGetTokenType( SPNEGO_TOKEN_HANDLE hSpnegoToken, int * piTokenType ) 382 { 383 int nReturn = SPNEGO_E_INVALID_PARAMETER; 384 SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken; 385 386 // Check parameters 387 if ( IsValidSpnegoToken( pSpnegoToken ) && 388 NULL != piTokenType && 389 pSpnegoToken) 390 { 391 392 // Check that the type in the structure makes sense 393 if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType || 394 SPNEGO_TOKEN_TARG == pSpnegoToken->ucTokenType ) 395 { 396 *piTokenType = pSpnegoToken->ucTokenType; 397 nReturn = SPNEGO_E_SUCCESS; 398 } 399 400 } // IF parameters OK 401 402 return nReturn; 403 } 404 405 ///////////////////////////////////////////////////////////////////////////// 406 // 407 // Function: 408 // spnegoIsMechTypeAvailable 409 // 410 // Parameters: 411 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE 412 // [in] MechOID - MechOID to search MechTypeList for 413 // [out] piMechTypeIndex - Filled out with index in MechTypeList 414 // element if MechOID is found. 415 // 416 // Returns: 417 // int Success - SPNEGO_E_SUCCESS 418 // Failure - SPNEGO API Error code 419 // 420 // Comments : 421 // hSpnegoToken must reference a token of type NegTokenInit. The 422 // function will search the MechTypeList element for an OID corresponding 423 // to the specified MechOID. If one is found, the index (0 based) will 424 // be passed into the piMechTypeIndex parameter. 425 // 426 //////////////////////////////////////////////////////////////////////////// 427 428 // Returns the Initial Mech Type in the MechList element in the NegInitToken. 429 int spnegoIsMechTypeAvailable( SPNEGO_TOKEN_HANDLE hSpnegoToken, SPNEGO_MECH_OID MechOID, int * piMechTypeIndex ) 430 { 431 int nReturn = SPNEGO_E_INVALID_PARAMETER; 432 SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken; 433 434 // Check parameters 435 if ( IsValidSpnegoToken( pSpnegoToken ) && 436 NULL != piMechTypeIndex && 437 IsValidMechOid( MechOID ) && 438 SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType ) 439 { 440 441 // Check if MechList is available 442 if ( pSpnegoToken->aElementArray[SPNEGO_INIT_MECHTYPES_ELEMENT].iElementPresent 443 == SPNEGO_TOKEN_ELEMENT_AVAILABLE ) 444 { 445 // Locate the MechOID in the list element 446 nReturn = FindMechOIDInMechList( 447 &pSpnegoToken->aElementArray[SPNEGO_INIT_MECHTYPES_ELEMENT], 448 MechOID, piMechTypeIndex ); 449 } 450 else 451 { 452 nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE; 453 } 454 455 } // IF parameters OK 456 457 return nReturn;; 458 } 459 460 ///////////////////////////////////////////////////////////////////////////// 461 // 462 // Function: 463 // spnegoGetContextFlags 464 // 465 // Parameters: 466 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE 467 // [out] pucContextFlags - Filled out with ContextFlags value. 468 // 469 // Returns: 470 // int Success - SPNEGO_E_SUCCESS 471 // Failure - SPNEGO API Error code 472 // 473 // Comments : 474 // hSpnegoToken must reference a token of type NegTokenInit. The 475 // function will copy data from the ContextFlags element into the 476 // location pucContextFlags points to. Note that the function will 477 // fail if the actual ContextFlags data appears invalid. 478 // 479 //////////////////////////////////////////////////////////////////////////// 480 481 int spnegoGetContextFlags( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pucContextFlags ) 482 { 483 int nReturn = SPNEGO_E_INVALID_PARAMETER; 484 SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken; 485 486 // Check parameters 487 if ( IsValidSpnegoToken( pSpnegoToken ) && 488 NULL != pucContextFlags && 489 SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType ) 490 { 491 492 // Check if ContextFlags is available 493 if ( pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].iElementPresent 494 == SPNEGO_TOKEN_ELEMENT_AVAILABLE ) 495 { 496 // The length should be two, the value should show a 1 bit difference in the difference byte, and 497 // the value must be valid 498 if ( pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].nDatalength == SPNEGO_NEGINIT_MAXLEN_REQFLAGS && 499 pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].pbData[0] == SPNEGO_NEGINIT_REQFLAGS_BITDIFF && 500 IsValidContextFlags( pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].pbData[1] ) ) 501 { 502 *pucContextFlags = pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].pbData[1]; 503 nReturn = SPNEGO_E_SUCCESS; 504 } 505 else 506 { 507 nReturn = SPNEGO_E_INVALID_ELEMENT; 508 } 509 510 } 511 else 512 { 513 nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE; 514 } 515 516 } // IF parameters OK 517 518 return nReturn;; 519 } 520 521 ///////////////////////////////////////////////////////////////////////////// 522 // 523 // Function: 524 // spnegoGetNegotiationResult 525 // 526 // Parameters: 527 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE 528 // [out] pnegResult - Filled out with NegResult value. 529 // 530 // Returns: 531 // int Success - SPNEGO_E_SUCCESS 532 // Failure - SPNEGO API Error code 533 // 534 // Comments : 535 // hSpnegoToken must reference a token of type NegTokenTarg. The 536 // function will copy data from the NegResult element into the 537 // location pointed to by pnegResult. Note that the function will 538 // fail if the actual NegResult data appears invalid. 539 // 540 //////////////////////////////////////////////////////////////////////////// 541 542 int spnegoGetNegotiationResult( SPNEGO_TOKEN_HANDLE hSpnegoToken, SPNEGO_NEGRESULT* pnegResult ) 543 { 544 int nReturn = SPNEGO_E_INVALID_PARAMETER; 545 SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken; 546 547 // Check parameters 548 if ( IsValidSpnegoToken( pSpnegoToken ) && 549 NULL != pnegResult && 550 SPNEGO_TOKEN_TARG == pSpnegoToken->ucTokenType ) 551 { 552 553 // Check if NegResult is available 554 if ( pSpnegoToken->aElementArray[SPNEGO_TARG_NEGRESULT_ELEMENT].iElementPresent 555 == SPNEGO_TOKEN_ELEMENT_AVAILABLE ) 556 { 557 // Must be 1 byte long and a valid value 558 if ( pSpnegoToken->aElementArray[SPNEGO_TARG_NEGRESULT_ELEMENT].nDatalength == SPNEGO_NEGTARG_MAXLEN_NEGRESULT && 559 IsValidNegResult( *pSpnegoToken->aElementArray[SPNEGO_TARG_NEGRESULT_ELEMENT].pbData ) ) 560 { 561 *pnegResult = *pSpnegoToken->aElementArray[SPNEGO_TARG_NEGRESULT_ELEMENT].pbData; 562 nReturn = SPNEGO_E_SUCCESS; 563 } 564 else 565 { 566 nReturn = SPNEGO_E_INVALID_ELEMENT; 567 } 568 } 569 else 570 { 571 nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE; 572 } 573 574 } // IF parameters OK 575 576 return nReturn;; 577 } 578 579 ///////////////////////////////////////////////////////////////////////////// 580 // 581 // Function: 582 // spnegoGetSupportedMechType 583 // 584 // Parameters: 585 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE 586 // [out] pMechOID - Filled out with Supported MechType value. 587 // 588 // Returns: 589 // int Success - SPNEGO_E_SUCCESS 590 // Failure - SPNEGO API Error code 591 // 592 // Comments : 593 // hSpnegoToken must reference a token of type NegTokenTarg. The 594 // function will check the Supported MechType element, and if it 595 // corresponds to a supported MechType ( spnego_mech_oid_Kerberos_V5_Legacy 596 // or spnego_mech_oid_Kerberos_V5 ), will set the location pointed 597 // to by pMechOID equal to the appropriate value. 598 // 599 //////////////////////////////////////////////////////////////////////////// 600 601 int spnegoGetSupportedMechType( SPNEGO_TOKEN_HANDLE hSpnegoToken, SPNEGO_MECH_OID* pMechOID ) 602 { 603 int nReturn = SPNEGO_E_INVALID_PARAMETER; 604 int nCtr = 0L; 605 long nLength = 0L; 606 SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken; 607 608 // Check parameters 609 if ( IsValidSpnegoToken( pSpnegoToken ) && 610 NULL != pMechOID && 611 SPNEGO_TOKEN_TARG == pSpnegoToken->ucTokenType ) 612 { 613 614 // Check if MechList is available 615 if ( pSpnegoToken->aElementArray[SPNEGO_TARG_SUPPMECH_ELEMENT].iElementPresent 616 == SPNEGO_TOKEN_ELEMENT_AVAILABLE ) 617 { 618 619 for ( nCtr = 0; 620 nReturn != SPNEGO_E_SUCCESS && 621 g_stcMechOIDList[nCtr].eMechanismOID != spnego_mech_oid_NotUsed; 622 nCtr++ ) 623 { 624 625 if ( ( nReturn = ASNDerCheckOID( 626 pSpnegoToken->aElementArray[SPNEGO_TARG_SUPPMECH_ELEMENT].pbData, 627 nCtr, 628 pSpnegoToken->aElementArray[SPNEGO_TARG_SUPPMECH_ELEMENT].nDatalength, 629 &nLength ) ) == SPNEGO_E_SUCCESS ) 630 { 631 *pMechOID = nCtr; 632 } 633 634 } // For enum MechOIDs 635 636 637 } 638 else 639 { 640 nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE; 641 } 642 643 } // IF parameters OK 644 645 return nReturn;; 646 } 647 648 ///////////////////////////////////////////////////////////////////////////// 649 // 650 // Function: 651 // spnegoTokenGetMechToken 652 // 653 // Parameters: 654 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE 655 // [out] pbTokenData - Buffer to copy MechToken into 656 // [in/out] pulDataLen - Length of pbTokenData buffer, filled out 657 // with actual size used upon function return. 658 // 659 // Returns: 660 // int Success - SPNEGO_E_SUCCESS 661 // Failure - SPNEGO API Error code 662 // 663 // Comments : 664 // hSpnegoToken can point to either NegTokenInit or a NegTokenTarg token. 665 // The function will copy the MechToken (the initial MechToken if 666 // NegTokenInit, the response MechToken if NegTokenTarg) from the 667 // underlying token into the buffer pointed to by pbTokenData. If 668 // pbTokenData is NULL, or the value in pulDataLen is too small, the 669 // function will return SPNEGO_E_BUFFER_TOO_SMALL and fill out pulDataLen 670 // with the minimum required buffer size. The token can then be passed 671 // to a GSS-API function for processing. 672 // 673 //////////////////////////////////////////////////////////////////////////// 674 675 int spnegoGetMechToken( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pbTokenData, unsigned long* pulDataLen ) 676 { 677 int nReturn = SPNEGO_E_INVALID_PARAMETER; 678 SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken; 679 SPNEGO_ELEMENT* pSpnegoElement = NULL; 680 681 // Check parameters 682 if ( IsValidSpnegoToken( pSpnegoToken ) && 683 NULL != pulDataLen ) 684 { 685 686 // Point at the proper Element 687 if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType ) 688 { 689 pSpnegoElement = &pSpnegoToken->aElementArray[SPNEGO_INIT_MECHTOKEN_ELEMENT]; 690 } 691 else 692 { 693 pSpnegoElement = &pSpnegoToken->aElementArray[SPNEGO_TARG_RESPTOKEN_ELEMENT]; 694 } 695 696 // Check if MechType is available 697 if ( SPNEGO_TOKEN_ELEMENT_AVAILABLE == pSpnegoElement->iElementPresent ) 698 { 699 // Check for Buffer too small conditions 700 if ( NULL == pbTokenData || 701 pSpnegoElement->nDatalength > *pulDataLen ) 702 { 703 *pulDataLen = pSpnegoElement->nDatalength; 704 nReturn = SPNEGO_E_BUFFER_TOO_SMALL; 705 } 706 else 707 { 708 // Copy Memory 709 memcpy( pbTokenData, pSpnegoElement->pbData, pSpnegoElement->nDatalength ); 710 *pulDataLen = pSpnegoElement->nDatalength; 711 nReturn = SPNEGO_E_SUCCESS; 712 } 713 } 714 else 715 { 716 nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE; 717 } 718 719 } // IF parameters OK 720 721 return nReturn;; 722 } 723 724 ///////////////////////////////////////////////////////////////////////////// 725 // 726 // Function: 727 // spnegoTokenGetMechListMIC 728 // 729 // Parameters: 730 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE 731 // [out] pbTokenData - Buffer to copy MechListMIC data into 732 // [in/out] pulDataLen - Length of pbTokenData buffer, filled out 733 // with actual size used upon function return. 734 // 735 // Returns: 736 // int Success - SPNEGO_E_SUCCESS 737 // Failure - SPNEGO API Error code 738 // 739 // Comments : 740 // hSpnegoToken can point to either NegTokenInit or a NegTokenTarg token. 741 // The function will copy the MechListMIC data from the underlying token 742 // into the buffer pointed to by pbTokenData. If pbTokenData is NULL, 743 // or the value in pulDataLen is too small, the function will return 744 // SPNEGO_E_BUFFER_TOO_SMALL and fill out pulDataLen with the minimum 745 // required buffer size. 746 // 747 //////////////////////////////////////////////////////////////////////////// 748 749 int spnegoGetMechListMIC( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pbMICData, unsigned long* pulDataLen ) 750 { 751 int nReturn = SPNEGO_E_INVALID_PARAMETER; 752 SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken; 753 SPNEGO_ELEMENT* pSpnegoElement = NULL; 754 755 // Check parameters 756 if ( IsValidSpnegoToken( pSpnegoToken ) && 757 NULL != pulDataLen ) 758 { 759 760 // Point at the proper Element 761 if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType ) 762 { 763 pSpnegoElement = &pSpnegoToken->aElementArray[SPNEGO_INIT_MECHLISTMIC_ELEMENT]; 764 } 765 else 766 { 767 pSpnegoElement = &pSpnegoToken->aElementArray[SPNEGO_TARG_MECHLISTMIC_ELEMENT]; 768 } 769 770 // Check if MechType is available 771 if ( SPNEGO_TOKEN_ELEMENT_AVAILABLE == pSpnegoElement->iElementPresent ) 772 { 773 // Check for Buffer too small conditions 774 if ( NULL == pbMICData || 775 pSpnegoElement->nDatalength > *pulDataLen ) 776 { 777 *pulDataLen = pSpnegoElement->nDatalength; 778 nReturn = SPNEGO_E_BUFFER_TOO_SMALL; 779 } 780 else 781 { 782 // Copy Memory 783 memcpy( pbMICData, pSpnegoElement->pbData, pSpnegoElement->nDatalength ); 784 *pulDataLen = pSpnegoElement->nDatalength; 785 nReturn = SPNEGO_E_SUCCESS; 786 } 787 } 788 else 789 { 790 nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE; 791 } 792 793 } // IF parameters OK 794 795 return nReturn;; 796 } 797 798