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