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 37extern 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 74int 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 116int 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 206int 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 309int 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 356void 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 381int 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. 429int 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 481int 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 542int 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 601int 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 675int 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 749int 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