"Fossies" - the Fresh Open Source Software Archive

Member "spnegohelp/spnego.c" (10 Apr 2005, 28050 Bytes) of package /linux/www/apache_httpd_modules/old/modgssapache-0.0.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

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