xref: /titanic_50/usr/src/lib/libsmbfs/smb/spnegoparse.c (revision 12b65585e720714b31036daaa2b30eb76014048e)
1*12b65585SGordon Ross // Copyright 2012 Nexenta Systems, Inc.  All rights reserved.
24bff34e3Sthurlow // Copyright (C) 2002 Microsoft Corporation
34bff34e3Sthurlow // All rights reserved.
44bff34e3Sthurlow //
54bff34e3Sthurlow // THIS CODE AND INFORMATION IS PROVIDED "AS IS"
64bff34e3Sthurlow // WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
74bff34e3Sthurlow // OR IMPLIED, INCLUDING BUT NOT LIMITED
84bff34e3Sthurlow // TO THE IMPLIED WARRANTIES OF MERCHANTIBILITY
94bff34e3Sthurlow // AND/OR FITNESS FOR A PARTICULAR PURPOSE.
104bff34e3Sthurlow //
114bff34e3Sthurlow // Date    - 10/08/2002
124bff34e3Sthurlow // Author  - Sanj Surati
134bff34e3Sthurlow 
144bff34e3Sthurlow /////////////////////////////////////////////////////////////
154bff34e3Sthurlow //
164bff34e3Sthurlow // SPNEGOPARSE.C
174bff34e3Sthurlow //
184bff34e3Sthurlow // SPNEGO Token Handler Source File
194bff34e3Sthurlow //
204bff34e3Sthurlow // Contains implementation of SPNEGO Token parsing functions.
214bff34e3Sthurlow //
224bff34e3Sthurlow /////////////////////////////////////////////////////////////
234bff34e3Sthurlow 
244bff34e3Sthurlow #include <stdlib.h>
254bff34e3Sthurlow #include <stdio.h>
264bff34e3Sthurlow #include <memory.h>
274bff34e3Sthurlow #include "spnego.h"
284bff34e3Sthurlow #include "derparse.h"
294bff34e3Sthurlow #include "spnegoparse.h"
304bff34e3Sthurlow 
314bff34e3Sthurlow //
324bff34e3Sthurlow // Defined in DERPARSE.C
334bff34e3Sthurlow //
344bff34e3Sthurlow 
354bff34e3Sthurlow extern MECH_OID g_stcMechOIDList [];
364bff34e3Sthurlow 
374bff34e3Sthurlow /**********************************************************************/
384bff34e3Sthurlow /**                                                                  **/
394bff34e3Sthurlow /**                                                                  **/
404bff34e3Sthurlow /**                                                                  **/
414bff34e3Sthurlow /**                                                                  **/
424bff34e3Sthurlow /**                 Local SPNEGO Helper definitions                  **/
434bff34e3Sthurlow /**                                                                  **/
444bff34e3Sthurlow /**                                                                  **/
454bff34e3Sthurlow /**                                                                  **/
464bff34e3Sthurlow /**                                                                  **/
474bff34e3Sthurlow /**********************************************************************/
484bff34e3Sthurlow 
494bff34e3Sthurlow 
504bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
514bff34e3Sthurlow //
524bff34e3Sthurlow // Function:
534bff34e3Sthurlow //    CalculateMinSpnegoInitTokenSize
544bff34e3Sthurlow //
554bff34e3Sthurlow // Parameters:
564bff34e3Sthurlow //    [in]  nMechTokenLength        -  Length of the MechToken Element
574bff34e3Sthurlow //    [in]  nMechListMICLength      -  Length of the MechListMIC Element
58*12b65585SGordon Ross //                                     (or negHints, if no MechToken)
594bff34e3Sthurlow //    [in]  mechOID                 -  OID for MechList
604bff34e3Sthurlow //    [in]  nReqFlagsAvailable      -  Is ContextFlags element available
614bff34e3Sthurlow //    [out] pnTokenSize             -  Filled out with total size of token
624bff34e3Sthurlow //    [out] pnInternalTokenLength   -  Filled out with length minus length
634bff34e3Sthurlow //                                     for initial token.
644bff34e3Sthurlow //
654bff34e3Sthurlow // Returns:
664bff34e3Sthurlow //    int   Success - SPNEGO_E_SUCCESS
674bff34e3Sthurlow //          Failure - SPNEGO API Error code
684bff34e3Sthurlow //
694bff34e3Sthurlow // Comments :
704bff34e3Sthurlow //    Calculates the required length for a SPNEGO NegTokenInit token based
714bff34e3Sthurlow //    on the supplied variable length values and which elements are present.
724bff34e3Sthurlow //    Note that because the lengths can be represented by an arbitrary
734bff34e3Sthurlow //    number of bytes in DER encodings, we actually calculate the lengths
744bff34e3Sthurlow //    backwards, so we always know how many bytes we will potentially be
754bff34e3Sthurlow //    writing out.
764bff34e3Sthurlow //
774bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
784bff34e3Sthurlow 
CalculateMinSpnegoInitTokenSize(long nMechTokenLength,long nMechListMICLength,SPNEGO_MECH_OID * mechOidLst,int mechOidCnt,int nReqFlagsAvailable,long * pnTokenSize,long * pnInternalTokenLength)794bff34e3Sthurlow int CalculateMinSpnegoInitTokenSize( long nMechTokenLength,
80*12b65585SGordon Ross       long nMechListMICLength, SPNEGO_MECH_OID *mechOidLst, int mechOidCnt,
814bff34e3Sthurlow                                  int nReqFlagsAvailable, long* pnTokenSize,
824bff34e3Sthurlow                                  long* pnInternalTokenLength )
834bff34e3Sthurlow {
844bff34e3Sthurlow    int   nReturn = SPNEGO_E_INVALID_LENGTH;
854bff34e3Sthurlow 
864bff34e3Sthurlow    // Start at 0.
874bff34e3Sthurlow    long  nTotalLength = 0;
884bff34e3Sthurlow    long  nTempLength= 0L;
894bff34e3Sthurlow 
904bff34e3Sthurlow    // We will calculate this by walking the token backwards
914bff34e3Sthurlow 
92*12b65585SGordon Ross    // Start with MIC Element (or negHints)
934bff34e3Sthurlow    if ( nMechListMICLength > 0L )
944bff34e3Sthurlow    {
954bff34e3Sthurlow       nTempLength = ASNDerCalcElementLength( nMechListMICLength, NULL );
964bff34e3Sthurlow 
974bff34e3Sthurlow       // Check for rollover error
984bff34e3Sthurlow       if ( nTempLength < nMechListMICLength )
994bff34e3Sthurlow       {
1004bff34e3Sthurlow          goto xEndTokenInitLength;
1014bff34e3Sthurlow       }
1024bff34e3Sthurlow 
1034bff34e3Sthurlow       nTotalLength += nTempLength;
1044bff34e3Sthurlow    }
1054bff34e3Sthurlow 
1064bff34e3Sthurlow    // Next is the MechToken
1074bff34e3Sthurlow    if ( nMechTokenLength > 0L )
1084bff34e3Sthurlow    {
1094bff34e3Sthurlow       nTempLength += ASNDerCalcElementLength( nMechTokenLength, NULL );
1104bff34e3Sthurlow 
1114bff34e3Sthurlow       // Check for rollover error
1124bff34e3Sthurlow       if ( nTempLength < nTotalLength )
1134bff34e3Sthurlow       {
1144bff34e3Sthurlow          goto xEndTokenInitLength;
1154bff34e3Sthurlow       }
1164bff34e3Sthurlow 
1174bff34e3Sthurlow       nTotalLength = nTempLength;
1184bff34e3Sthurlow    }
1194bff34e3Sthurlow 
1204bff34e3Sthurlow    // Next is the ReqFlags
1214bff34e3Sthurlow    if ( nReqFlagsAvailable )
1224bff34e3Sthurlow    {
1234bff34e3Sthurlow       nTempLength += ASNDerCalcElementLength( SPNEGO_NEGINIT_MAXLEN_REQFLAGS, NULL );
1244bff34e3Sthurlow 
1254bff34e3Sthurlow       // Check for rollover error
1264bff34e3Sthurlow       if ( nTempLength < nTotalLength )
1274bff34e3Sthurlow       {
1284bff34e3Sthurlow          goto xEndTokenInitLength;
1294bff34e3Sthurlow       }
1304bff34e3Sthurlow 
1314bff34e3Sthurlow       nTotalLength = nTempLength;
1324bff34e3Sthurlow    }
1334bff34e3Sthurlow 
1344bff34e3Sthurlow    // Next is the MechList - This is REQUIRED
135*12b65585SGordon Ross    nTempLength += ASNDerCalcMechListLength( mechOidLst, mechOidCnt, NULL );
1364bff34e3Sthurlow 
1374bff34e3Sthurlow    // Check for rollover error
1384bff34e3Sthurlow    if ( nTempLength < nTotalLength )
1394bff34e3Sthurlow    {
1404bff34e3Sthurlow       goto xEndTokenInitLength;
1414bff34e3Sthurlow    }
1424bff34e3Sthurlow 
1434bff34e3Sthurlow    nTotalLength = nTempLength;
1444bff34e3Sthurlow 
1454bff34e3Sthurlow    // Following four fields are the basic header tokens
1464bff34e3Sthurlow 
1474bff34e3Sthurlow    // Sequence Token
1484bff34e3Sthurlow    nTempLength += ASNDerCalcTokenLength( nTotalLength, 0L );
1494bff34e3Sthurlow 
1504bff34e3Sthurlow    // Check for rollover error
1514bff34e3Sthurlow    if ( nTempLength < nTotalLength )
1524bff34e3Sthurlow    {
1534bff34e3Sthurlow       goto xEndTokenInitLength;
1544bff34e3Sthurlow    }
1554bff34e3Sthurlow 
1564bff34e3Sthurlow    nTotalLength = nTempLength;
1574bff34e3Sthurlow 
1584bff34e3Sthurlow    // Neg Token Identifier Token
1594bff34e3Sthurlow    nTempLength += ASNDerCalcTokenLength( nTotalLength, 0L );
1604bff34e3Sthurlow 
1614bff34e3Sthurlow    // Check for rollover error
1624bff34e3Sthurlow    if ( nTempLength < nTotalLength )
1634bff34e3Sthurlow    {
1644bff34e3Sthurlow       goto xEndTokenInitLength;
1654bff34e3Sthurlow    }
1664bff34e3Sthurlow 
1674bff34e3Sthurlow    nTotalLength = nTempLength;
1684bff34e3Sthurlow 
1694bff34e3Sthurlow    // SPNEGO OID Token
1704bff34e3Sthurlow    nTempLength += g_stcMechOIDList[spnego_mech_oid_Spnego].iLen;
1714bff34e3Sthurlow 
1724bff34e3Sthurlow    // Check for rollover error
1734bff34e3Sthurlow    if ( nTempLength < nTotalLength )
1744bff34e3Sthurlow    {
1754bff34e3Sthurlow       goto xEndTokenInitLength;
1764bff34e3Sthurlow    }
1774bff34e3Sthurlow 
1784bff34e3Sthurlow    nTotalLength = nTempLength;
1794bff34e3Sthurlow 
1804bff34e3Sthurlow    // App Constructed Token
1814bff34e3Sthurlow    nTempLength += ASNDerCalcTokenLength( nTotalLength, 0L );
1824bff34e3Sthurlow 
1834bff34e3Sthurlow    // Check for rollover error
1844bff34e3Sthurlow    if ( nTempLength < nTotalLength )
1854bff34e3Sthurlow    {
1864bff34e3Sthurlow       goto xEndTokenInitLength;
1874bff34e3Sthurlow    }
1884bff34e3Sthurlow 
1894bff34e3Sthurlow    // The internal length doesn't include the number of bytes
1904bff34e3Sthurlow    // for the initial token
1914bff34e3Sthurlow    *pnInternalTokenLength = nTotalLength;
1924bff34e3Sthurlow    nTotalLength = nTempLength;
1934bff34e3Sthurlow 
1944bff34e3Sthurlow    // We're done
1954bff34e3Sthurlow    *pnTokenSize = nTotalLength;
1964bff34e3Sthurlow    nReturn = SPNEGO_E_SUCCESS;
1974bff34e3Sthurlow 
1984bff34e3Sthurlow xEndTokenInitLength:
1994bff34e3Sthurlow 
2004bff34e3Sthurlow    return nReturn;
2014bff34e3Sthurlow 
2024bff34e3Sthurlow }
2034bff34e3Sthurlow 
2044bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
2054bff34e3Sthurlow //
2064bff34e3Sthurlow // Function:
2074bff34e3Sthurlow //    CreateSpnegoInitToken
2084bff34e3Sthurlow //
2094bff34e3Sthurlow // Parameters:
210*12b65585SGordon Ross //    [in]  pMechTypeList           -  OID array
211*12b65585SGordon Ross //    [in]  MechTypeCnt             -  OID array length
2124bff34e3Sthurlow //    [in]  ucContextFlags          -  ContextFlags value
2134bff34e3Sthurlow //    [in]  pbMechToken             -  Mech Token Binary Data
2144bff34e3Sthurlow //    [in]  ulMechTokenLen          -  Length of Mech Token
215*12b65585SGordon Ross //    [in]  pbMechListMIC           -  MechListMIC Binary Data (or negHints)
2164bff34e3Sthurlow //    [in]  ulMechListMICn          -  Length of MechListMIC
2174bff34e3Sthurlow //    [out] pbTokenData             -  Buffer to write token into.
2184bff34e3Sthurlow //    [in]  nTokenLength            -  Length of pbTokenData buffer
2194bff34e3Sthurlow //    [in]  nInternalTokenLength    -  Length of full token without leading
2204bff34e3Sthurlow //                                     token bytes.
2214bff34e3Sthurlow //
2224bff34e3Sthurlow // Returns:
2234bff34e3Sthurlow //    int   Success - SPNEGO_E_SUCCESS
2244bff34e3Sthurlow //          Failure - SPNEGO API Error code
2254bff34e3Sthurlow //
2264bff34e3Sthurlow // Comments :
2274bff34e3Sthurlow //    Uses DER to fill out pbTokenData with a SPNEGO NegTokenInit Token
2284bff34e3Sthurlow //    Note that because the lengths can be represented by an arbitrary
2294bff34e3Sthurlow //    number of bytes in DER encodings, we actually calculate the lengths
2304bff34e3Sthurlow //    backwards, so we always know how many bytes we will potentially be
2314bff34e3Sthurlow //    writing out.
2324bff34e3Sthurlow //
233*12b65585SGordon Ross //    This function is also used to create an SPNEGO "hint", as described in
234*12b65585SGordon Ross //    [MS-SPNG] sec. 2.2.1 negTokenInit2.  The "hint" looks almost identical
235*12b65585SGordon Ross //    to a NegTokenInit, but has a "negHints" field inserted before the MIC.
236*12b65585SGordon Ross //    A normal SPNEGO negTokenInit2 contains only the mech list and the
237*12b65585SGordon Ross //    negHints.  To avoid a giant copy/paste of this function, we pass the
238*12b65585SGordon Ross //    negHints as the MIC arg, and pass NULL as the MechToken to indicate
239*12b65585SGordon Ross //    that we're creating a Hint rather than an Init, and use the correct
240*12b65585SGordon Ross //    type when writing out the MIC (or negHints) element.
241*12b65585SGordon Ross //
2424bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
2434bff34e3Sthurlow 
CreateSpnegoInitToken(SPNEGO_MECH_OID * pMechTypeList,long MechTypeCnt,unsigned char ucContextFlags,unsigned char * pbMechToken,unsigned long ulMechTokenLen,unsigned char * pbMechListMIC,unsigned long ulMechListMICLen,unsigned char * pbTokenData,long nTokenLength,long nInternalTokenLength)244*12b65585SGordon Ross int CreateSpnegoInitToken( SPNEGO_MECH_OID *pMechTypeList, long MechTypeCnt,
2454bff34e3Sthurlow           unsigned char ucContextFlags, unsigned char* pbMechToken,
2464bff34e3Sthurlow           unsigned long ulMechTokenLen, unsigned char* pbMechListMIC,
2474bff34e3Sthurlow           unsigned long ulMechListMICLen, unsigned char* pbTokenData,
2484bff34e3Sthurlow           long nTokenLength, long nInternalTokenLength )
2494bff34e3Sthurlow {
2504bff34e3Sthurlow    int   nReturn = SPNEGO_E_INVALID_LENGTH;
2514bff34e3Sthurlow 
2524bff34e3Sthurlow    // Start at 0.
2534bff34e3Sthurlow    long  nTempLength= 0L;
2544bff34e3Sthurlow    long  nTotalBytesWritten = 0L;
2554bff34e3Sthurlow    long  nInternalLength = 0L;
2564bff34e3Sthurlow 
2574bff34e3Sthurlow    unsigned char* pbWriteTokenData = pbTokenData + nTokenLength;
2584bff34e3Sthurlow 
2594bff34e3Sthurlow    // Temporary buffer to hold the REQ Flags as BIT String Data
2604bff34e3Sthurlow    unsigned char  abTempReqFlags[SPNEGO_NEGINIT_MAXLEN_REQFLAGS];
2614bff34e3Sthurlow 
2624bff34e3Sthurlow 
2634bff34e3Sthurlow    // We will write the token out backwards to properly handle the cases
2644bff34e3Sthurlow    // where the length bytes become adjustable
2654bff34e3Sthurlow 
266*12b65585SGordon Ross    // Start with MIC Element (or negHints)
2674bff34e3Sthurlow    if ( ulMechListMICLen > 0L )
2684bff34e3Sthurlow    {
269*12b65585SGordon Ross       unsigned char ucType;
2704bff34e3Sthurlow       nTempLength = ASNDerCalcElementLength( ulMechListMICLen, &nInternalLength );
2714bff34e3Sthurlow 
272*12b65585SGordon Ross       // Decrease the pbWriteTokenData, now we know the length and write it out.
273*12b65585SGordon Ross       // Note: When MechTokenLen == 0, we're writing a negTokenInit2 and the
274*12b65585SGordon Ross       // MIC arg is really negHints, written as a constructed sequence.
275*12b65585SGordon Ross       // Otherwise we're writing a negTokenInit, and the MIC is an OCTETSTRING.
276*12b65585SGordon Ross       ucType = (ulMechTokenLen == 0) ?
277*12b65585SGordon Ross          SPNEGO_CONSTRUCTED_SEQUENCE : OCTETSTRING;
2784bff34e3Sthurlow 
2794bff34e3Sthurlow       pbWriteTokenData -= nTempLength;
2804bff34e3Sthurlow       nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGINIT_ELEMENT_MECHLISTMIC,
281*12b65585SGordon Ross                               ucType, pbMechListMIC, ulMechListMICLen );
2824bff34e3Sthurlow 
2834bff34e3Sthurlow       // Adjust Values and sanity check
2844bff34e3Sthurlow       nTotalBytesWritten += nTempLength;
2854bff34e3Sthurlow       nInternalTokenLength -= nTempLength;
2864bff34e3Sthurlow 
2874bff34e3Sthurlow       if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
2884bff34e3Sthurlow       {
2894bff34e3Sthurlow          goto xEndWriteNegTokenInit;
2904bff34e3Sthurlow       }
2914bff34e3Sthurlow 
2924bff34e3Sthurlow    }  // IF MechListMIC is present
2934bff34e3Sthurlow 
2944bff34e3Sthurlow    // Next is the MechToken
2954bff34e3Sthurlow    if ( ulMechTokenLen > 0L )
2964bff34e3Sthurlow    {
2974bff34e3Sthurlow       nTempLength = ASNDerCalcElementLength( ulMechTokenLen, &nInternalLength );
2984bff34e3Sthurlow 
2994bff34e3Sthurlow       // Decrease the pbWriteTokenData, now we know the length and
3004bff34e3Sthurlow       // write it out.
3014bff34e3Sthurlow       pbWriteTokenData -= nTempLength;
3024bff34e3Sthurlow       nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGINIT_ELEMENT_MECHTOKEN,
3034bff34e3Sthurlow                               OCTETSTRING, pbMechToken, ulMechTokenLen );
3044bff34e3Sthurlow       // Adjust Values and sanity check
3054bff34e3Sthurlow       nTotalBytesWritten += nTempLength;
3064bff34e3Sthurlow       nInternalTokenLength -= nTempLength;
3074bff34e3Sthurlow 
3084bff34e3Sthurlow       if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
3094bff34e3Sthurlow       {
3104bff34e3Sthurlow          goto xEndWriteNegTokenInit;
3114bff34e3Sthurlow       }
3124bff34e3Sthurlow 
3134bff34e3Sthurlow    }  // IF MechToken Length is present
3144bff34e3Sthurlow 
3154bff34e3Sthurlow    // Next is the ReqFlags
3164bff34e3Sthurlow    if ( ucContextFlags > 0L )
3174bff34e3Sthurlow    {
3184bff34e3Sthurlow 
3194bff34e3Sthurlow       nTempLength = ASNDerCalcElementLength( SPNEGO_NEGINIT_MAXLEN_REQFLAGS, &nInternalLength );
3204bff34e3Sthurlow 
3214bff34e3Sthurlow       // We need a byte that indicates how many bits difference between the number
3224bff34e3Sthurlow       // of bits used in final octet (we only have one) and the max (8)
3234bff34e3Sthurlow 
3244bff34e3Sthurlow       abTempReqFlags[0] = SPNEGO_NEGINIT_REQFLAGS_BITDIFF;
3254bff34e3Sthurlow       abTempReqFlags[1] = ucContextFlags;
3264bff34e3Sthurlow 
3274bff34e3Sthurlow       // Decrease the pbWriteTokenData, now we know the length and
3284bff34e3Sthurlow       // write it out.
3294bff34e3Sthurlow       pbWriteTokenData -= nTempLength;
3304bff34e3Sthurlow       nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGINIT_ELEMENT_REQFLAGS,
3314bff34e3Sthurlow                               BITSTRING, abTempReqFlags, SPNEGO_NEGINIT_MAXLEN_REQFLAGS );
3324bff34e3Sthurlow 
3334bff34e3Sthurlow       // Adjust Values and sanity check
3344bff34e3Sthurlow       nTotalBytesWritten += nTempLength;
3354bff34e3Sthurlow       nInternalTokenLength -= nTempLength;
3364bff34e3Sthurlow 
3374bff34e3Sthurlow       if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
3384bff34e3Sthurlow       {
3394bff34e3Sthurlow          goto xEndWriteNegTokenInit;
3404bff34e3Sthurlow       }
3414bff34e3Sthurlow 
3424bff34e3Sthurlow    }  // IF ContextFlags
3434bff34e3Sthurlow 
3444bff34e3Sthurlow    // Next is the MechList - This is REQUIRED
345*12b65585SGordon Ross    nTempLength = ASNDerCalcMechListLength( pMechTypeList, MechTypeCnt, &nInternalLength );
3464bff34e3Sthurlow 
3474bff34e3Sthurlow    // Decrease the pbWriteTokenData, now we know the length and
3484bff34e3Sthurlow    // write it out.
3494bff34e3Sthurlow    pbWriteTokenData -= nTempLength;
350*12b65585SGordon Ross    nTempLength = ASNDerWriteMechList( pbWriteTokenData, pMechTypeList, MechTypeCnt );
3514bff34e3Sthurlow 
3524bff34e3Sthurlow    // Adjust Values and sanity check
3534bff34e3Sthurlow    nTotalBytesWritten += nTempLength;
3544bff34e3Sthurlow    nInternalTokenLength -= nTempLength;
3554bff34e3Sthurlow 
3564bff34e3Sthurlow    if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
3574bff34e3Sthurlow    {
3584bff34e3Sthurlow       goto xEndWriteNegTokenInit;
3594bff34e3Sthurlow    }
3604bff34e3Sthurlow 
3614bff34e3Sthurlow    // The next tokens we're writing out reflect the total number of bytes
3624bff34e3Sthurlow    // we have actually written out.
3634bff34e3Sthurlow 
3644bff34e3Sthurlow    // Sequence Token
3654bff34e3Sthurlow    nTempLength = ASNDerCalcTokenLength( nTotalBytesWritten, 0L );
3664bff34e3Sthurlow 
3674bff34e3Sthurlow    // Decrease the pbWriteTokenData, now we know the length and
3684bff34e3Sthurlow    // write it out.
3694bff34e3Sthurlow    pbWriteTokenData -= nTempLength;
3704bff34e3Sthurlow    nTempLength = ASNDerWriteToken( pbWriteTokenData, SPNEGO_CONSTRUCTED_SEQUENCE,
3714bff34e3Sthurlow                                     NULL, nTotalBytesWritten );
3724bff34e3Sthurlow 
3734bff34e3Sthurlow    // Adjust Values and sanity check
3744bff34e3Sthurlow    nTotalBytesWritten += nTempLength;
3754bff34e3Sthurlow    nInternalTokenLength -= nTempLength;
3764bff34e3Sthurlow 
3774bff34e3Sthurlow    if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
3784bff34e3Sthurlow    {
3794bff34e3Sthurlow       goto xEndWriteNegTokenInit;
3804bff34e3Sthurlow    }
3814bff34e3Sthurlow 
3824bff34e3Sthurlow    // Neg Init Token Identifier Token
3834bff34e3Sthurlow    nTempLength = ASNDerCalcTokenLength( nTotalBytesWritten, 0L );
3844bff34e3Sthurlow 
3854bff34e3Sthurlow    // Decrease the pbWriteTokenData, now we know the length and
3864bff34e3Sthurlow    // write it out.
3874bff34e3Sthurlow    pbWriteTokenData -= nTempLength;
3884bff34e3Sthurlow    nTempLength = ASNDerWriteToken( pbWriteTokenData, SPNEGO_NEGINIT_TOKEN_IDENTIFIER,
3894bff34e3Sthurlow                                     NULL, nTotalBytesWritten );
3904bff34e3Sthurlow 
3914bff34e3Sthurlow    // Adjust Values and sanity check
3924bff34e3Sthurlow    nTotalBytesWritten += nTempLength;
3934bff34e3Sthurlow    nInternalTokenLength -= nTempLength;
3944bff34e3Sthurlow 
3954bff34e3Sthurlow    if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
3964bff34e3Sthurlow    {
3974bff34e3Sthurlow       goto xEndWriteNegTokenInit;
3984bff34e3Sthurlow    }
3994bff34e3Sthurlow 
4004bff34e3Sthurlow    // SPNEGO OID Token
4014bff34e3Sthurlow    nTempLength = g_stcMechOIDList[spnego_mech_oid_Spnego].iLen;
4024bff34e3Sthurlow 
4034bff34e3Sthurlow    // Decrease the pbWriteTokenData, now we know the length and
4044bff34e3Sthurlow    // write it out.
4054bff34e3Sthurlow    pbWriteTokenData -= nTempLength;
4064bff34e3Sthurlow    nTempLength = ASNDerWriteOID( pbWriteTokenData, spnego_mech_oid_Spnego );
4074bff34e3Sthurlow 
4084bff34e3Sthurlow    // Adjust Values and sanity check
4094bff34e3Sthurlow    nTotalBytesWritten += nTempLength;
4104bff34e3Sthurlow    nInternalTokenLength -= nTempLength;
4114bff34e3Sthurlow 
4124bff34e3Sthurlow    if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
4134bff34e3Sthurlow    {
4144bff34e3Sthurlow       goto xEndWriteNegTokenInit;
4154bff34e3Sthurlow    }
4164bff34e3Sthurlow 
4174bff34e3Sthurlow    // App Constructed Token
4184bff34e3Sthurlow    nTempLength = ASNDerCalcTokenLength( nTotalBytesWritten, 0L );
4194bff34e3Sthurlow 
4204bff34e3Sthurlow    // Decrease the pbWriteTokenData, now we know the length and
4214bff34e3Sthurlow    // write it out.
4224bff34e3Sthurlow    pbWriteTokenData -= nTempLength;
4234bff34e3Sthurlow    nTempLength = ASNDerWriteToken( pbWriteTokenData, SPNEGO_NEGINIT_APP_CONSTRUCT,
4244bff34e3Sthurlow                                     NULL, nTotalBytesWritten );
4254bff34e3Sthurlow 
4264bff34e3Sthurlow    // Adjust Values and sanity check
4274bff34e3Sthurlow    nTotalBytesWritten += nTempLength;
4284bff34e3Sthurlow 
4294bff34e3Sthurlow    // Don't adjust the internal token length here, it doesn't account
4304bff34e3Sthurlow    // the initial bytes written out (we really don't need to keep
4314bff34e3Sthurlow    // a running count here, but for debugging, it helps to be able
4324bff34e3Sthurlow    // to see the total number of bytes written out as well as the
4334bff34e3Sthurlow    // number of bytes left to write).
4344bff34e3Sthurlow 
4354bff34e3Sthurlow    if ( nTotalBytesWritten == nTokenLength && nInternalTokenLength == 0 &&
4364bff34e3Sthurlow          pbWriteTokenData == pbTokenData )
4374bff34e3Sthurlow    {
4384bff34e3Sthurlow       nReturn = SPNEGO_E_SUCCESS;
4394bff34e3Sthurlow    }
4404bff34e3Sthurlow 
4414bff34e3Sthurlow xEndWriteNegTokenInit:
4424bff34e3Sthurlow 
4434bff34e3Sthurlow    return nReturn;
4444bff34e3Sthurlow 
4454bff34e3Sthurlow }
4464bff34e3Sthurlow 
4474bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
4484bff34e3Sthurlow //
4494bff34e3Sthurlow // Function:
4504bff34e3Sthurlow //    CalculateMinSpnegoTargTokenSize
4514bff34e3Sthurlow //
4524bff34e3Sthurlow // Parameters:
4534bff34e3Sthurlow //    [in]  MechType                -  Supported MechType
4544bff34e3Sthurlow //    [in]  spnegoNegResult         -  Neg Result
4554bff34e3Sthurlow //    [in]  nMechTokenLength        -  Length of the MechToken Element
4564bff34e3Sthurlow //    [in]  nMechListMICLength      -  Length of the MechListMIC Element
4574bff34e3Sthurlow //    [out] pnTokenSize             -  Filled out with total size of token
4584bff34e3Sthurlow //    [out] pnInternalTokenLength   -  Filled out with length minus length
4594bff34e3Sthurlow //                                     for initial token.
4604bff34e3Sthurlow //
4614bff34e3Sthurlow // Returns:
4624bff34e3Sthurlow //    int   Success - SPNEGO_E_SUCCESS
4634bff34e3Sthurlow //          Failure - SPNEGO API Error code
4644bff34e3Sthurlow //
4654bff34e3Sthurlow // Comments :
4664bff34e3Sthurlow //    Calculates the required length for a SPNEGO NegTokenTarg token based
4674bff34e3Sthurlow //    on the supplied variable length values and which elements are present.
4684bff34e3Sthurlow //    Note that because the lengths can be represented by an arbitrary
4694bff34e3Sthurlow //    number of bytes in DER encodings, we actually calculate the lengths
4704bff34e3Sthurlow //    backwards, so we always know how many bytes we will potentially be
4714bff34e3Sthurlow //    writing out.
4724bff34e3Sthurlow //
4734bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
4744bff34e3Sthurlow 
CalculateMinSpnegoTargTokenSize(SPNEGO_MECH_OID MechType,SPNEGO_NEGRESULT spnegoNegResult,long nMechTokenLen,long nMechListMICLen,long * pnTokenSize,long * pnInternalTokenLength)4754bff34e3Sthurlow int CalculateMinSpnegoTargTokenSize( SPNEGO_MECH_OID MechType,
4764bff34e3Sthurlow                                     SPNEGO_NEGRESULT spnegoNegResult, long nMechTokenLen,
4774bff34e3Sthurlow                                     long nMechListMICLen, long* pnTokenSize,
4784bff34e3Sthurlow                                     long* pnInternalTokenLength )
4794bff34e3Sthurlow {
4804bff34e3Sthurlow    int   nReturn = SPNEGO_E_INVALID_LENGTH;
4814bff34e3Sthurlow 
4824bff34e3Sthurlow    // Start at 0.
4834bff34e3Sthurlow    long  nTotalLength = 0;
4844bff34e3Sthurlow    long  nTempLength= 0L;
4854bff34e3Sthurlow 
4864bff34e3Sthurlow    // We will calculate this by walking the token backwards
4874bff34e3Sthurlow 
4884bff34e3Sthurlow    // Start with MIC Element
4894bff34e3Sthurlow    if ( nMechListMICLen > 0L )
4904bff34e3Sthurlow    {
4914bff34e3Sthurlow       nTempLength = ASNDerCalcElementLength( nMechListMICLen, NULL );
4924bff34e3Sthurlow 
4934bff34e3Sthurlow       // Check for rollover error
4944bff34e3Sthurlow       if ( nTempLength < nMechListMICLen )
4954bff34e3Sthurlow       {
4964bff34e3Sthurlow          goto xEndTokenTargLength;
4974bff34e3Sthurlow       }
4984bff34e3Sthurlow 
4994bff34e3Sthurlow       nTotalLength += nTempLength;
5004bff34e3Sthurlow    }
5014bff34e3Sthurlow 
5024bff34e3Sthurlow    // Next is the MechToken
5034bff34e3Sthurlow    if ( nMechTokenLen > 0L )
5044bff34e3Sthurlow    {
5054bff34e3Sthurlow       nTempLength += ASNDerCalcElementLength( nMechTokenLen, NULL );
5064bff34e3Sthurlow 
5074bff34e3Sthurlow       // Check for rollover error
5084bff34e3Sthurlow       if ( nTempLength < nTotalLength )
5094bff34e3Sthurlow       {
5104bff34e3Sthurlow          goto xEndTokenTargLength;
5114bff34e3Sthurlow       }
5124bff34e3Sthurlow 
5134bff34e3Sthurlow       nTotalLength = nTempLength;
5144bff34e3Sthurlow    }
5154bff34e3Sthurlow 
5164bff34e3Sthurlow    // Supported MechType
5174bff34e3Sthurlow    if ( spnego_mech_oid_NotUsed != MechType )
5184bff34e3Sthurlow    {
5194bff34e3Sthurlow       // Supported MechOID element - we use the token function since
5204bff34e3Sthurlow       // we already know the size of the OID token and value
5214bff34e3Sthurlow       nTempLength += ASNDerCalcElementLength( g_stcMechOIDList[MechType].iActualDataLen,
5224bff34e3Sthurlow                                              NULL );
5234bff34e3Sthurlow 
5244bff34e3Sthurlow       // Check for rollover error
5254bff34e3Sthurlow       if ( nTempLength < nTotalLength )
5264bff34e3Sthurlow       {
5274bff34e3Sthurlow          goto xEndTokenTargLength;
5284bff34e3Sthurlow       }
5294bff34e3Sthurlow 
5304bff34e3Sthurlow       nTotalLength = nTempLength;
5314bff34e3Sthurlow 
5324bff34e3Sthurlow    }  // IF MechType is available
5334bff34e3Sthurlow 
5344bff34e3Sthurlow    // NegResult Element
5354bff34e3Sthurlow    if ( spnego_negresult_NotUsed != spnegoNegResult )
5364bff34e3Sthurlow    {
5374bff34e3Sthurlow       nTempLength += ASNDerCalcElementLength( SPNEGO_NEGTARG_MAXLEN_NEGRESULT, NULL );
5384bff34e3Sthurlow 
5394bff34e3Sthurlow       // Check for rollover error
5404bff34e3Sthurlow       if ( nTempLength < nTotalLength )
5414bff34e3Sthurlow       {
5424bff34e3Sthurlow          goto xEndTokenTargLength;
5434bff34e3Sthurlow       }
5444bff34e3Sthurlow 
5454bff34e3Sthurlow       nTotalLength = nTempLength;
5464bff34e3Sthurlow 
5474bff34e3Sthurlow    }  // IF negResult is available
5484bff34e3Sthurlow 
5494bff34e3Sthurlow    // Following two fields are the basic header tokens
5504bff34e3Sthurlow 
5514bff34e3Sthurlow    // Sequence Token
5524bff34e3Sthurlow    nTempLength += ASNDerCalcTokenLength( nTotalLength, 0L );
5534bff34e3Sthurlow 
5544bff34e3Sthurlow    // Check for rollover error
5554bff34e3Sthurlow    if ( nTempLength < nTotalLength )
5564bff34e3Sthurlow    {
5574bff34e3Sthurlow       goto xEndTokenTargLength;
5584bff34e3Sthurlow    }
5594bff34e3Sthurlow 
5604bff34e3Sthurlow    nTotalLength = nTempLength;
5614bff34e3Sthurlow 
5624bff34e3Sthurlow    // Neg Token Identifier Token
5634bff34e3Sthurlow    nTempLength += ASNDerCalcTokenLength( nTotalLength, 0L );
5644bff34e3Sthurlow 
5654bff34e3Sthurlow    // Check for rollover error
5664bff34e3Sthurlow    if ( nTempLength < nTotalLength )
5674bff34e3Sthurlow    {
5684bff34e3Sthurlow       goto xEndTokenTargLength;
5694bff34e3Sthurlow    }
5704bff34e3Sthurlow 
5714bff34e3Sthurlow    // The internal length doesn't include the number of bytes
5724bff34e3Sthurlow    // for the initial token
5734bff34e3Sthurlow    *pnInternalTokenLength = nTotalLength;
5744bff34e3Sthurlow    nTotalLength = nTempLength;
5754bff34e3Sthurlow 
5764bff34e3Sthurlow    // We're done
5774bff34e3Sthurlow    *pnTokenSize = nTotalLength;
5784bff34e3Sthurlow    nReturn = SPNEGO_E_SUCCESS;
5794bff34e3Sthurlow 
5804bff34e3Sthurlow xEndTokenTargLength:
5814bff34e3Sthurlow 
5824bff34e3Sthurlow    return nReturn;
5834bff34e3Sthurlow 
5844bff34e3Sthurlow }
5854bff34e3Sthurlow 
5864bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
5874bff34e3Sthurlow //
5884bff34e3Sthurlow // Function:
5894bff34e3Sthurlow //    CreateSpnegoTargToken
5904bff34e3Sthurlow //
5914bff34e3Sthurlow // Parameters:
5924bff34e3Sthurlow //    [in]  MechType                -  Supported MechType
5934bff34e3Sthurlow //    [in]  eNegResult              -  NegResult value
5944bff34e3Sthurlow //    [in]  pbMechToken             -  Mech Token Binary Data
5954bff34e3Sthurlow //    [in]  ulMechTokenLen          -  Length of Mech Token
5964bff34e3Sthurlow //    [in]  pbMechListMIC           -  MechListMIC Binary Data
5974bff34e3Sthurlow //    [in]  ulMechListMICn          -  Length of MechListMIC
5984bff34e3Sthurlow //    [out] pbTokenData             -  Buffer to write token into.
5994bff34e3Sthurlow //    [in]  nTokenLength            -  Length of pbTokenData buffer
6004bff34e3Sthurlow //    [in]  nInternalTokenLength    -  Length of full token without leading
6014bff34e3Sthurlow //                                     token bytes.
6024bff34e3Sthurlow //
6034bff34e3Sthurlow // Returns:
6044bff34e3Sthurlow //    int   Success - SPNEGO_E_SUCCESS
6054bff34e3Sthurlow //          Failure - SPNEGO API Error code
6064bff34e3Sthurlow //
6074bff34e3Sthurlow // Comments :
6084bff34e3Sthurlow //    Uses DER to fill out pbTokenData with a SPNEGO NegTokenTarg Token
6094bff34e3Sthurlow //    Note that because the lengths can be represented by an arbitrary
6104bff34e3Sthurlow //    number of bytes in DER encodings, we actually calculate the lengths
6114bff34e3Sthurlow //    backwards, so we always know how many bytes we will potentially be
6124bff34e3Sthurlow //    writing out.
6134bff34e3Sthurlow //
6144bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
6154bff34e3Sthurlow 
CreateSpnegoTargToken(SPNEGO_MECH_OID MechType,SPNEGO_NEGRESULT eNegResult,unsigned char * pbMechToken,unsigned long ulMechTokenLen,unsigned char * pbMechListMIC,unsigned long ulMechListMICLen,unsigned char * pbTokenData,long nTokenLength,long nInternalTokenLength)6164bff34e3Sthurlow int CreateSpnegoTargToken( SPNEGO_MECH_OID MechType,
6174bff34e3Sthurlow           SPNEGO_NEGRESULT eNegResult, unsigned char* pbMechToken,
6184bff34e3Sthurlow           unsigned long ulMechTokenLen, unsigned char* pbMechListMIC,
6194bff34e3Sthurlow           unsigned long ulMechListMICLen, unsigned char* pbTokenData,
6204bff34e3Sthurlow           long nTokenLength, long nInternalTokenLength )
6214bff34e3Sthurlow {
6224bff34e3Sthurlow    int   nReturn = SPNEGO_E_INVALID_LENGTH;
6234bff34e3Sthurlow 
6244bff34e3Sthurlow    // Start at 0.
6254bff34e3Sthurlow    long  nTempLength= 0L;
6264bff34e3Sthurlow    long  nTotalBytesWritten = 0L;
6274bff34e3Sthurlow    long  nInternalLength = 0L;
6284bff34e3Sthurlow 
6294bff34e3Sthurlow    unsigned char  ucTemp = 0;
6304bff34e3Sthurlow 
6314bff34e3Sthurlow    // We will write the token out backwards to properly handle the cases
6324bff34e3Sthurlow    // where the length bytes become adjustable, so the write location
6334bff34e3Sthurlow    // is initialized to point *just* past the end of the buffer.
6344bff34e3Sthurlow 
6354bff34e3Sthurlow    unsigned char* pbWriteTokenData = pbTokenData + nTokenLength;
6364bff34e3Sthurlow 
6374bff34e3Sthurlow 
6384bff34e3Sthurlow    // Start with MIC Element
6394bff34e3Sthurlow    if ( ulMechListMICLen > 0L )
6404bff34e3Sthurlow    {
6414bff34e3Sthurlow       nTempLength = ASNDerCalcElementLength( ulMechListMICLen, &nInternalLength );
6424bff34e3Sthurlow 
6434bff34e3Sthurlow       // Decrease the pbWriteTokenData, now we know the length and
6444bff34e3Sthurlow       // write it out.
6454bff34e3Sthurlow 
6464bff34e3Sthurlow       pbWriteTokenData -= nTempLength;
6474bff34e3Sthurlow       nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGTARG_ELEMENT_MECHLISTMIC,
6484bff34e3Sthurlow                               OCTETSTRING, pbMechListMIC, ulMechListMICLen );
6494bff34e3Sthurlow 
6504bff34e3Sthurlow       // Adjust Values and sanity check
6514bff34e3Sthurlow       nTotalBytesWritten += nTempLength;
6524bff34e3Sthurlow       nInternalTokenLength -= nTempLength;
6534bff34e3Sthurlow 
6544bff34e3Sthurlow       if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
6554bff34e3Sthurlow       {
6564bff34e3Sthurlow          goto xEndWriteNegTokenTarg;
6574bff34e3Sthurlow       }
6584bff34e3Sthurlow 
6594bff34e3Sthurlow    }  // IF MechListMIC is present
6604bff34e3Sthurlow 
6614bff34e3Sthurlow    // Next is the MechToken
6624bff34e3Sthurlow    if ( ulMechTokenLen > 0L )
6634bff34e3Sthurlow    {
6644bff34e3Sthurlow       nTempLength = ASNDerCalcElementLength( ulMechTokenLen, &nInternalLength );
6654bff34e3Sthurlow 
6664bff34e3Sthurlow       // Decrease the pbWriteTokenData, now we know the length and
6674bff34e3Sthurlow       // write it out.
6684bff34e3Sthurlow       pbWriteTokenData -= nTempLength;
6694bff34e3Sthurlow       nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGTARG_ELEMENT_RESPONSETOKEN,
6704bff34e3Sthurlow                               OCTETSTRING, pbMechToken, ulMechTokenLen );
6714bff34e3Sthurlow       // Adjust Values and sanity check
6724bff34e3Sthurlow       nTotalBytesWritten += nTempLength;
6734bff34e3Sthurlow       nInternalTokenLength -= nTempLength;
6744bff34e3Sthurlow 
6754bff34e3Sthurlow       if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
6764bff34e3Sthurlow       {
6774bff34e3Sthurlow          goto xEndWriteNegTokenTarg;
6784bff34e3Sthurlow       }
6794bff34e3Sthurlow 
6804bff34e3Sthurlow    }  // IF MechToken Length is present
6814bff34e3Sthurlow 
6824bff34e3Sthurlow    // Supported Mech Type
6834bff34e3Sthurlow    if ( spnego_mech_oid_NotUsed != MechType )
6844bff34e3Sthurlow    {
6854bff34e3Sthurlow 
6864bff34e3Sthurlow       nTempLength = ASNDerCalcElementLength( g_stcMechOIDList[MechType].iActualDataLen,
6874bff34e3Sthurlow                                              &nInternalLength );
6884bff34e3Sthurlow 
6894bff34e3Sthurlow       // Decrease the pbWriteTokenData, now we know the length and
6904bff34e3Sthurlow       // write it out.
6914bff34e3Sthurlow       pbWriteTokenData -= nTempLength;
6924bff34e3Sthurlow       nTempLength = ASNDerWriteToken( pbWriteTokenData, SPNEGO_NEGTARG_ELEMENT_SUPPORTEDMECH,
6934bff34e3Sthurlow                                        g_stcMechOIDList[MechType].ucOid,
6944bff34e3Sthurlow                                        g_stcMechOIDList[MechType].iLen );
6954bff34e3Sthurlow 
6964bff34e3Sthurlow       // Adjust Values and sanity check
6974bff34e3Sthurlow       nTotalBytesWritten += nTempLength;
6984bff34e3Sthurlow       nInternalTokenLength -= nTempLength;
6994bff34e3Sthurlow 
7004bff34e3Sthurlow       if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
7014bff34e3Sthurlow       {
7024bff34e3Sthurlow          goto xEndWriteNegTokenTarg;
7034bff34e3Sthurlow       }
7044bff34e3Sthurlow 
7054bff34e3Sthurlow    }  // IF MechType is present
7064bff34e3Sthurlow 
7074bff34e3Sthurlow    // Neg Result
7084bff34e3Sthurlow    // NegResult Element
7094bff34e3Sthurlow    if ( spnego_negresult_NotUsed != eNegResult )
7104bff34e3Sthurlow    {
7114bff34e3Sthurlow       ucTemp = (unsigned char) eNegResult;
7124bff34e3Sthurlow 
7134bff34e3Sthurlow       nTempLength = ASNDerCalcElementLength( SPNEGO_NEGTARG_MAXLEN_NEGRESULT, &nInternalLength );
7144bff34e3Sthurlow 
7154bff34e3Sthurlow       // Decrease the pbWriteTokenData, now we know the length and
7164bff34e3Sthurlow       // write it out.
7174bff34e3Sthurlow       pbWriteTokenData -= nTempLength;
7184bff34e3Sthurlow       nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGTARG_ELEMENT_NEGRESULT,
7194bff34e3Sthurlow                               ENUMERATED, &ucTemp, SPNEGO_NEGTARG_MAXLEN_NEGRESULT );
7204bff34e3Sthurlow 
7214bff34e3Sthurlow       // Adjust Values and sanity check
7224bff34e3Sthurlow       nTotalBytesWritten += nTempLength;
7234bff34e3Sthurlow       nInternalTokenLength -= nTempLength;
7244bff34e3Sthurlow 
7254bff34e3Sthurlow       if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
7264bff34e3Sthurlow       {
7274bff34e3Sthurlow          goto xEndWriteNegTokenTarg;
7284bff34e3Sthurlow       }
7294bff34e3Sthurlow 
7304bff34e3Sthurlow    }  // If eNegResult is available
7314bff34e3Sthurlow 
7324bff34e3Sthurlow    // The next tokens we're writing out reflect the total number of bytes
7334bff34e3Sthurlow    // we have actually written out.
7344bff34e3Sthurlow 
7354bff34e3Sthurlow    // Sequence Token
7364bff34e3Sthurlow    nTempLength = ASNDerCalcTokenLength( nTotalBytesWritten, 0L );
7374bff34e3Sthurlow 
7384bff34e3Sthurlow    // Decrease the pbWriteTokenData, now we know the length and
7394bff34e3Sthurlow    // write it out.
7404bff34e3Sthurlow    pbWriteTokenData -= nTempLength;
7414bff34e3Sthurlow    nTempLength = ASNDerWriteToken( pbWriteTokenData, SPNEGO_CONSTRUCTED_SEQUENCE,
7424bff34e3Sthurlow                                     NULL, nTotalBytesWritten );
7434bff34e3Sthurlow 
7444bff34e3Sthurlow    // Adjust Values and sanity check
7454bff34e3Sthurlow    nTotalBytesWritten += nTempLength;
7464bff34e3Sthurlow    nInternalTokenLength -= nTempLength;
7474bff34e3Sthurlow 
7484bff34e3Sthurlow    if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
7494bff34e3Sthurlow    {
7504bff34e3Sthurlow       goto xEndWriteNegTokenTarg;
7514bff34e3Sthurlow    }
7524bff34e3Sthurlow 
7534bff34e3Sthurlow    // Neg Targ Token Identifier Token
7544bff34e3Sthurlow    nTempLength = ASNDerCalcTokenLength( nTotalBytesWritten, 0L );
7554bff34e3Sthurlow 
7564bff34e3Sthurlow    // Decrease the pbWriteTokenData, now we know the length and
7574bff34e3Sthurlow    // write it out.
7584bff34e3Sthurlow    pbWriteTokenData -= nTempLength;
7594bff34e3Sthurlow    nTempLength = ASNDerWriteToken( pbWriteTokenData, SPNEGO_NEGTARG_TOKEN_IDENTIFIER,
7604bff34e3Sthurlow                                     NULL, nTotalBytesWritten );
7614bff34e3Sthurlow 
7624bff34e3Sthurlow    // Adjust Values and sanity check
7634bff34e3Sthurlow    nTotalBytesWritten += nTempLength;
7644bff34e3Sthurlow 
7654bff34e3Sthurlow    // Don't adjust the internal token length here, it doesn't account
7664bff34e3Sthurlow    // the initial bytes written out (we really don't need to keep
7674bff34e3Sthurlow    // a running count here, but for debugging, it helps to be able
7684bff34e3Sthurlow    // to see the total number of bytes written out as well as the
7694bff34e3Sthurlow    // number of bytes left to write).
7704bff34e3Sthurlow 
7714bff34e3Sthurlow    if ( nTotalBytesWritten == nTokenLength && nInternalTokenLength == 0 &&
7724bff34e3Sthurlow          pbWriteTokenData == pbTokenData )
7734bff34e3Sthurlow    {
7744bff34e3Sthurlow       nReturn = SPNEGO_E_SUCCESS;
7754bff34e3Sthurlow    }
7764bff34e3Sthurlow 
7774bff34e3Sthurlow 
7784bff34e3Sthurlow xEndWriteNegTokenTarg:
7794bff34e3Sthurlow 
7804bff34e3Sthurlow    return nReturn;
7814bff34e3Sthurlow 
7824bff34e3Sthurlow 
7834bff34e3Sthurlow }
7844bff34e3Sthurlow 
7854bff34e3Sthurlow 
7864bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
7874bff34e3Sthurlow //
7884bff34e3Sthurlow // Function:
7894bff34e3Sthurlow //    AllocEmptySpnegoToken
7904bff34e3Sthurlow //
7914bff34e3Sthurlow // Parameters:
7924bff34e3Sthurlow //    [in]  ucCopyData        -  Flag to copy data or pointer.
7934bff34e3Sthurlow //    [in]  ulFlags           -  Flags for SPNEGO_TOKEN data member.
7944bff34e3Sthurlow //    [in]  pbTokenData       -  Binary token data.
7954bff34e3Sthurlow //    [in]  ulTokenSize       -  Size of pbTokenData.
7964bff34e3Sthurlow //
7974bff34e3Sthurlow // Returns:
7984bff34e3Sthurlow //    SPNEGO_TOKEN*  Success - Pointer to initialized SPNEGO_TOKEN struct
7994bff34e3Sthurlow //                   Failure - NULL
8004bff34e3Sthurlow //
8014bff34e3Sthurlow // Comments :
8024bff34e3Sthurlow //    Allocates a SPNEGO_TOKEN data structure and initializes it.  Based on
8034bff34e3Sthurlow //    the value of ucCopyData, if non-zero, we copy the data into a buffer
8044bff34e3Sthurlow //    we allocate in this function, otherwise, we copy the data pointer
8054bff34e3Sthurlow //    direcly.
8064bff34e3Sthurlow //
8074bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
8084bff34e3Sthurlow 
AllocEmptySpnegoToken(unsigned char ucCopyData,unsigned long ulFlags,unsigned char * pbTokenData,unsigned long ulTokenSize)8094bff34e3Sthurlow SPNEGO_TOKEN* AllocEmptySpnegoToken( unsigned char ucCopyData, unsigned long ulFlags,
8104bff34e3Sthurlow                                     unsigned char * pbTokenData, unsigned long ulTokenSize )
8114bff34e3Sthurlow {
8124bff34e3Sthurlow    SPNEGO_TOKEN*  pSpnegoToken = (SPNEGO_TOKEN*) calloc( 1, sizeof(SPNEGO_TOKEN) );
8134bff34e3Sthurlow 
8144bff34e3Sthurlow    if ( NULL != pSpnegoToken )
8154bff34e3Sthurlow    {
8164bff34e3Sthurlow       // Set the token size
8174bff34e3Sthurlow       pSpnegoToken->nStructSize = SPNEGO_TOKEN_SIZE;
8184bff34e3Sthurlow 
8194bff34e3Sthurlow       // Initialize the element array
8204bff34e3Sthurlow       InitSpnegoTokenElementArray( pSpnegoToken );
8214bff34e3Sthurlow 
8224bff34e3Sthurlow       // Assign the flags value
8234bff34e3Sthurlow       pSpnegoToken->ulFlags = ulFlags;
8244bff34e3Sthurlow 
8254bff34e3Sthurlow       //
8264bff34e3Sthurlow       // IF ucCopyData is TRUE, we will allocate a buffer and copy data into it.
8274bff34e3Sthurlow       // Otherwise, we will just copy the pointer and the length.  This is so we
8284bff34e3Sthurlow       // can cut out additional allocations for performance reasons
8294bff34e3Sthurlow       //
8304bff34e3Sthurlow 
8314bff34e3Sthurlow       if ( SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA == ucCopyData )
8324bff34e3Sthurlow       {
8334bff34e3Sthurlow          // Alloc the internal buffer.  Cleanup on failure.
8344bff34e3Sthurlow          pSpnegoToken->pbBinaryData = (unsigned char*) calloc( ulTokenSize, sizeof(unsigned char) );
8354bff34e3Sthurlow 
8364bff34e3Sthurlow          if ( NULL != pSpnegoToken->pbBinaryData )
8374bff34e3Sthurlow          {
8384bff34e3Sthurlow             // We must ALWAYS free this buffer
8394bff34e3Sthurlow             pSpnegoToken->ulFlags |= SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA;
8404bff34e3Sthurlow 
8414bff34e3Sthurlow             // Copy the data locally
8424bff34e3Sthurlow             memcpy( pSpnegoToken->pbBinaryData, pbTokenData, ulTokenSize );
8434bff34e3Sthurlow             pSpnegoToken->ulBinaryDataLen = ulTokenSize;
8444bff34e3Sthurlow          }
8454bff34e3Sthurlow          else
8464bff34e3Sthurlow          {
8474bff34e3Sthurlow             free( pSpnegoToken );
8484bff34e3Sthurlow             pSpnegoToken = NULL;
8494bff34e3Sthurlow          }
8504bff34e3Sthurlow 
8514bff34e3Sthurlow       }  // IF ucCopyData
8524bff34e3Sthurlow       else
8534bff34e3Sthurlow       {
8544bff34e3Sthurlow          // Copy the pointer and the length directly - ulFlags will control whether or not
8554bff34e3Sthurlow          // we are allowed to free the value
8564bff34e3Sthurlow 
8574bff34e3Sthurlow          pSpnegoToken->pbBinaryData = pbTokenData;
8584bff34e3Sthurlow          pSpnegoToken->ulBinaryDataLen = ulTokenSize;
8594bff34e3Sthurlow       }
8604bff34e3Sthurlow 
8614bff34e3Sthurlow    }
8624bff34e3Sthurlow 
8634bff34e3Sthurlow    return pSpnegoToken;
8644bff34e3Sthurlow }
8654bff34e3Sthurlow 
8664bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
8674bff34e3Sthurlow //
8684bff34e3Sthurlow // Function:
8694bff34e3Sthurlow //    FreeSpnegoToken
8704bff34e3Sthurlow //
8714bff34e3Sthurlow // Parameters:
8724bff34e3Sthurlow //    [in]  pSpnegoToken      -  Points to SPNEGO_TOKEN to free.
8734bff34e3Sthurlow //
8744bff34e3Sthurlow // Returns:
8754bff34e3Sthurlow //    void
8764bff34e3Sthurlow //
8774bff34e3Sthurlow // Comments :
8784bff34e3Sthurlow //    If non-NULL, interprets pSpnegoToken, freeing any internal allocations
8794bff34e3Sthurlow //    and finally the actual structure.
8804bff34e3Sthurlow //
8814bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
8824bff34e3Sthurlow 
FreeSpnegoToken(SPNEGO_TOKEN * pSpnegoToken)8834bff34e3Sthurlow void FreeSpnegoToken( SPNEGO_TOKEN* pSpnegoToken )
8844bff34e3Sthurlow {
8854bff34e3Sthurlow    if ( NULL != pSpnegoToken )
8864bff34e3Sthurlow    {
8874bff34e3Sthurlow 
8884bff34e3Sthurlow       // Cleanup internal allocation per the flags
8894bff34e3Sthurlow       if ( pSpnegoToken->ulFlags & SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA &&
8904bff34e3Sthurlow          NULL != pSpnegoToken->pbBinaryData )
8914bff34e3Sthurlow       {
8924bff34e3Sthurlow          free( pSpnegoToken->pbBinaryData );
8934bff34e3Sthurlow          pSpnegoToken->pbBinaryData = NULL;
8944bff34e3Sthurlow       }
8954bff34e3Sthurlow 
8964bff34e3Sthurlow       free ( pSpnegoToken );
8974bff34e3Sthurlow    }
8984bff34e3Sthurlow }
8994bff34e3Sthurlow 
9004bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
9014bff34e3Sthurlow //
9024bff34e3Sthurlow // Function:
9034bff34e3Sthurlow //    InitSpnegoTokenElementArray
9044bff34e3Sthurlow //
9054bff34e3Sthurlow // Parameters:
9064bff34e3Sthurlow //    [in]  pSpnegoToken      -  Points to SPNEGO_TOKEN structure.
9074bff34e3Sthurlow //
9084bff34e3Sthurlow // Returns:
9094bff34e3Sthurlow //    void
9104bff34e3Sthurlow //
9114bff34e3Sthurlow // Comments :
9124bff34e3Sthurlow //    Initializes the element array data member of a SPNEGO_TOKEN data
9134bff34e3Sthurlow //    structure.
9144bff34e3Sthurlow //
9154bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
9164bff34e3Sthurlow 
InitSpnegoTokenElementArray(SPNEGO_TOKEN * pSpnegoToken)9174bff34e3Sthurlow void InitSpnegoTokenElementArray( SPNEGO_TOKEN* pSpnegoToken )
9184bff34e3Sthurlow {
9194bff34e3Sthurlow    int   nCtr;
9204bff34e3Sthurlow 
9214bff34e3Sthurlow    // Set the number of elemnts
9224bff34e3Sthurlow    pSpnegoToken->nNumElements = MAX_NUM_TOKEN_ELEMENTS;
9234bff34e3Sthurlow 
9244bff34e3Sthurlow    //
9254bff34e3Sthurlow    // Initially, all elements are unavailable
9264bff34e3Sthurlow    //
9274bff34e3Sthurlow 
9284bff34e3Sthurlow    for ( nCtr = 0; nCtr < MAX_NUM_TOKEN_ELEMENTS; nCtr++ )
9294bff34e3Sthurlow    {
9304bff34e3Sthurlow       // Set the element size as well
9314bff34e3Sthurlow       pSpnegoToken->aElementArray[ nCtr ].nStructSize = SPNEGO_ELEMENT_SIZE;
9324bff34e3Sthurlow       pSpnegoToken->aElementArray[ nCtr ].iElementPresent = SPNEGO_TOKEN_ELEMENT_UNAVAILABLE;
9334bff34e3Sthurlow    }
9344bff34e3Sthurlow 
9354bff34e3Sthurlow }
9364bff34e3Sthurlow 
9374bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
9384bff34e3Sthurlow //
9394bff34e3Sthurlow // Function:
9404bff34e3Sthurlow //    InitSpnegoTokenType
9414bff34e3Sthurlow //
9424bff34e3Sthurlow // Parameters:
9434bff34e3Sthurlow //    [in]  pSpnegoToken            -  Points to SPNEGO_TOKEN structure.
9444bff34e3Sthurlow //    [out] pnTokenLength           -  Filled out with total token length
9454bff34e3Sthurlow //    [out] pnRemainingTokenLength  -  Filled out with remaining length
9464bff34e3Sthurlow //                                     after header is parsed
9474bff34e3Sthurlow //    [out] ppbFirstElement         -  Filled out with pointer to first
9484bff34e3Sthurlow //                                     element after header info.
9494bff34e3Sthurlow //
9504bff34e3Sthurlow // Returns:
9514bff34e3Sthurlow //    int   Success - SPNEGO_E_SUCCESS
9524bff34e3Sthurlow //          Failure - SPNEGO API Error code
9534bff34e3Sthurlow //
9544bff34e3Sthurlow // Comments :
9554bff34e3Sthurlow //    Walks the underlying binary data for a SPNEGO_TOKEN data structure
9564bff34e3Sthurlow //    and determines the type of the underlying token based on token header
9574bff34e3Sthurlow //    information.
9584bff34e3Sthurlow //
9594bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
9604bff34e3Sthurlow 
InitSpnegoTokenType(SPNEGO_TOKEN * pSpnegoToken,long * pnTokenLength,long * pnRemainingTokenLength,unsigned char ** ppbFirstElement)9614bff34e3Sthurlow int InitSpnegoTokenType( SPNEGO_TOKEN* pSpnegoToken, long* pnTokenLength,
9624bff34e3Sthurlow                            long* pnRemainingTokenLength, unsigned char** ppbFirstElement )
9634bff34e3Sthurlow {
9644bff34e3Sthurlow    int   nReturn = SPNEGO_E_INVALID_TOKEN;
9654bff34e3Sthurlow    long  nActualTokenLength = 0L;
9664bff34e3Sthurlow    long  nBoundaryLength = pSpnegoToken->ulBinaryDataLen;
9674bff34e3Sthurlow    unsigned char* pbTokenData = pSpnegoToken->pbBinaryData;
9684bff34e3Sthurlow 
9694bff34e3Sthurlow    //
9704bff34e3Sthurlow    // First byte MUST be either an APP_CONSTRUCT or the NEGTARG_TOKEN_TARG
9714bff34e3Sthurlow    //
9724bff34e3Sthurlow 
9734bff34e3Sthurlow    if ( SPNEGO_NEGINIT_APP_CONSTRUCT == *pbTokenData )
9744bff34e3Sthurlow    {
9754bff34e3Sthurlow       // Validate the above token - this will tell us the actual length of the token
9764bff34e3Sthurlow       // per the encoding (minus the actual token bytes)
9774bff34e3Sthurlow       if ( ( nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_NEGINIT_APP_CONSTRUCT, 0L, nBoundaryLength,
9784bff34e3Sthurlow                                           pnTokenLength, &nActualTokenLength ) )
9794bff34e3Sthurlow                        == SPNEGO_E_SUCCESS )
9804bff34e3Sthurlow       {
9814bff34e3Sthurlow          // Initialize the remaining token length value.  This will be used
9824bff34e3Sthurlow          // to tell the caller how much token there is left once we've parsed
9834bff34e3Sthurlow          // the header (they could calculate it from the other values, but this
9844bff34e3Sthurlow          // is a bit friendlier)
9854bff34e3Sthurlow          *pnRemainingTokenLength = *pnTokenLength;
9864bff34e3Sthurlow 
9874bff34e3Sthurlow          // Make adjustments to next token
9884bff34e3Sthurlow          pbTokenData += nActualTokenLength;
9894bff34e3Sthurlow          nBoundaryLength -= nActualTokenLength;
9904bff34e3Sthurlow 
9914bff34e3Sthurlow          // The next token should be an OID
9924bff34e3Sthurlow          if ( ( nReturn = ASNDerCheckOID( pbTokenData, spnego_mech_oid_Spnego, nBoundaryLength,
9934bff34e3Sthurlow                                           &nActualTokenLength ) ) == SPNEGO_E_SUCCESS )
9944bff34e3Sthurlow          {
9954bff34e3Sthurlow             // Make adjustments to next token
9964bff34e3Sthurlow             pbTokenData += nActualTokenLength;
9974bff34e3Sthurlow             nBoundaryLength -= nActualTokenLength;
9984bff34e3Sthurlow             *pnRemainingTokenLength -= nActualTokenLength;
9994bff34e3Sthurlow 
10004bff34e3Sthurlow             // The next token should specify the NegTokenInit
10014bff34e3Sthurlow             if ( ( nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_NEGINIT_TOKEN_IDENTIFIER,
10024bff34e3Sthurlow                                                 *pnRemainingTokenLength, nBoundaryLength, pnTokenLength,
10034bff34e3Sthurlow                                                 &nActualTokenLength ) )
10044bff34e3Sthurlow                              == SPNEGO_E_SUCCESS )
10054bff34e3Sthurlow             {
10064bff34e3Sthurlow                // Make adjustments to next token
10074bff34e3Sthurlow                pbTokenData += nActualTokenLength;
10084bff34e3Sthurlow                nBoundaryLength -= nActualTokenLength;
10094bff34e3Sthurlow                *pnRemainingTokenLength -= nActualTokenLength;
10104bff34e3Sthurlow 
10114bff34e3Sthurlow                // The next token should specify the start of a sequence
10124bff34e3Sthurlow                if ( ( nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_CONSTRUCTED_SEQUENCE,
10134bff34e3Sthurlow                                                    *pnRemainingTokenLength, nBoundaryLength, pnTokenLength,
10144bff34e3Sthurlow                                                    &nActualTokenLength ) )
10154bff34e3Sthurlow                                 == SPNEGO_E_SUCCESS )
10164bff34e3Sthurlow                {
10174bff34e3Sthurlow                   // NegTokenInit header is now checked out!
10184bff34e3Sthurlow 
10194bff34e3Sthurlow                   // Make adjustments to next token
10204bff34e3Sthurlow                   *pnRemainingTokenLength -= nActualTokenLength;
10214bff34e3Sthurlow 
10224bff34e3Sthurlow                   // Store pointer to first element
10234bff34e3Sthurlow                   *ppbFirstElement = pbTokenData + nActualTokenLength;
10244bff34e3Sthurlow                   pSpnegoToken->ucTokenType = SPNEGO_TOKEN_INIT;
10254bff34e3Sthurlow                }  // IF Check Sequence Token
10264bff34e3Sthurlow 
10274bff34e3Sthurlow             }  // IF Check NegTokenInit token
10284bff34e3Sthurlow 
10294bff34e3Sthurlow 
10304bff34e3Sthurlow          }  // IF Check for SPNEGO OID
10314bff34e3Sthurlow 
10324bff34e3Sthurlow 
10334bff34e3Sthurlow       }  // IF check app construct token
10344bff34e3Sthurlow 
10354bff34e3Sthurlow    }
10364bff34e3Sthurlow    else if ( SPNEGO_NEGTARG_TOKEN_IDENTIFIER == *pbTokenData )
10374bff34e3Sthurlow    {
10384bff34e3Sthurlow 
10394bff34e3Sthurlow       // The next token should specify the NegTokenInit
10404bff34e3Sthurlow       if ( ( nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_NEGTARG_TOKEN_IDENTIFIER,
10414bff34e3Sthurlow                                           *pnRemainingTokenLength, nBoundaryLength, pnTokenLength,
10424bff34e3Sthurlow                                           &nActualTokenLength ) )
10434bff34e3Sthurlow                        == SPNEGO_E_SUCCESS )
10444bff34e3Sthurlow       {
10454bff34e3Sthurlow          // Initialize the remaining token length value.  This will be used
10464bff34e3Sthurlow          // to tell the caller how much token there is left once we've parsed
10474bff34e3Sthurlow          // the header (they could calculate it from the other values, but this
10484bff34e3Sthurlow          // is a bit friendlier)
10494bff34e3Sthurlow          *pnRemainingTokenLength = *pnTokenLength;
10504bff34e3Sthurlow 
10514bff34e3Sthurlow          // Make adjustments to next token
10524bff34e3Sthurlow          pbTokenData += nActualTokenLength;
10534bff34e3Sthurlow          nBoundaryLength -= nActualTokenLength;
10544bff34e3Sthurlow 
10554bff34e3Sthurlow          // The next token should specify the start of a sequence
10564bff34e3Sthurlow          if ( ( nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_CONSTRUCTED_SEQUENCE,
10574bff34e3Sthurlow                                              *pnRemainingTokenLength, nBoundaryLength, pnTokenLength,
10584bff34e3Sthurlow                                              &nActualTokenLength ) )
10594bff34e3Sthurlow                           == SPNEGO_E_SUCCESS )
10604bff34e3Sthurlow          {
10614bff34e3Sthurlow             // NegTokenInit header is now checked out!
10624bff34e3Sthurlow 
10634bff34e3Sthurlow             // Make adjustments to next token
10644bff34e3Sthurlow             *pnRemainingTokenLength -= nActualTokenLength;
10654bff34e3Sthurlow 
10664bff34e3Sthurlow             // Store pointer to first element
10674bff34e3Sthurlow             *ppbFirstElement = pbTokenData + nActualTokenLength;
10684bff34e3Sthurlow             pSpnegoToken->ucTokenType = SPNEGO_TOKEN_TARG;
10694bff34e3Sthurlow          }  // IF Check Sequence Token
10704bff34e3Sthurlow 
10714bff34e3Sthurlow       }  // IF Check NegTokenInit token
10724bff34e3Sthurlow 
10734bff34e3Sthurlow    }  // ELSE IF it's a NegTokenTarg
10744bff34e3Sthurlow 
10754bff34e3Sthurlow    return nReturn;
10764bff34e3Sthurlow }
10774bff34e3Sthurlow 
10784bff34e3Sthurlow 
10794bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
10804bff34e3Sthurlow //
10814bff34e3Sthurlow // Function:
10824bff34e3Sthurlow //    GetSpnegoInitTokenMechList
10834bff34e3Sthurlow //
10844bff34e3Sthurlow // Parameters:
10854bff34e3Sthurlow //    [in]  pbTokenData             -  Points to binary MechList element
10864bff34e3Sthurlow //                                     in NegTokenInit.
10874bff34e3Sthurlow //    [in]  nMechListLength         -  Length of the MechList
10884bff34e3Sthurlow //    [out] pSpnegoElement          -  Filled out with MechList Element
10894bff34e3Sthurlow //                                     data.
10904bff34e3Sthurlow //
10914bff34e3Sthurlow // Returns:
10924bff34e3Sthurlow //    int   Success - SPNEGO_E_SUCCESS
10934bff34e3Sthurlow //          Failure - SPNEGO API Error code
10944bff34e3Sthurlow //
10954bff34e3Sthurlow // Comments :
10964bff34e3Sthurlow //    Checks that pbTokenData is pointing at something that at least
10974bff34e3Sthurlow //    *looks* like a MechList and then fills out the supplied
10984bff34e3Sthurlow //    SPNEGO_ELEMENT structure.
10994bff34e3Sthurlow //
11004bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
11014bff34e3Sthurlow 
GetSpnegoInitTokenMechList(unsigned char * pbTokenData,int nMechListLength,SPNEGO_ELEMENT * pSpnegoElement)11024bff34e3Sthurlow int GetSpnegoInitTokenMechList( unsigned char* pbTokenData, int nMechListLength,
11034bff34e3Sthurlow                                  SPNEGO_ELEMENT* pSpnegoElement )
11044bff34e3Sthurlow {
11054bff34e3Sthurlow    int   nReturn = SPNEGO_E_INVALID_TOKEN;
11064bff34e3Sthurlow    long  nLength = 0L;
11074bff34e3Sthurlow    long  nActualTokenLength = 0L;
11084bff34e3Sthurlow 
11094bff34e3Sthurlow    // Actual MechList is prepended by a Constructed Sequence Token
11104bff34e3Sthurlow    if ( ( nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_CONSTRUCTED_SEQUENCE,
11114bff34e3Sthurlow                                        nMechListLength, nMechListLength,
11124bff34e3Sthurlow                                        &nLength, &nActualTokenLength ) )
11134bff34e3Sthurlow                              == SPNEGO_E_SUCCESS )
11144bff34e3Sthurlow    {
11154bff34e3Sthurlow       // Adjust for this token
11164bff34e3Sthurlow       nMechListLength -= nActualTokenLength;
11174bff34e3Sthurlow       pbTokenData += nActualTokenLength;
11184bff34e3Sthurlow 
11194bff34e3Sthurlow       // Perform simple validation of the actual MechList (i.e. ensure that
11204bff34e3Sthurlow       // the OIDs in the MechList are reasonable).
11214bff34e3Sthurlow 
11224bff34e3Sthurlow       if ( ( nReturn = ValidateMechList( pbTokenData, nLength ) ) == SPNEGO_E_SUCCESS )
11234bff34e3Sthurlow       {
11244bff34e3Sthurlow          // Initialize the element now
11254bff34e3Sthurlow          pSpnegoElement->eElementType = spnego_init_mechtypes;
11264bff34e3Sthurlow          pSpnegoElement->iElementPresent = SPNEGO_TOKEN_ELEMENT_AVAILABLE;
11274bff34e3Sthurlow          pSpnegoElement->type = SPNEGO_MECHLIST_TYPE;
11284bff34e3Sthurlow          pSpnegoElement->nDatalength = nLength;
11294bff34e3Sthurlow          pSpnegoElement->pbData = pbTokenData;
11304bff34e3Sthurlow       }
11314bff34e3Sthurlow 
11324bff34e3Sthurlow    }  // IF Check Token
11334bff34e3Sthurlow 
11344bff34e3Sthurlow    return nReturn;
11354bff34e3Sthurlow }
11364bff34e3Sthurlow 
11374bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
11384bff34e3Sthurlow //
11394bff34e3Sthurlow // Function:
11404bff34e3Sthurlow //    InitSpnegoTokenElementFromBasicType
11414bff34e3Sthurlow //
11424bff34e3Sthurlow // Parameters:
11434bff34e3Sthurlow //    [in]  pbTokenData             -  Points to binary element data in
11444bff34e3Sthurlow //                                     a SPNEGO token.
11454bff34e3Sthurlow //    [in]  nElementLength          -  Length of the element
11464bff34e3Sthurlow //    [in]  ucExpectedType          -  Expected DER type.
11474bff34e3Sthurlow //    [in]  spnegoElementType       -  Which element is this?
11484bff34e3Sthurlow //    [out] pSpnegoElement          -  Filled out with element data.
11494bff34e3Sthurlow //
11504bff34e3Sthurlow // Returns:
11514bff34e3Sthurlow //    int   Success - SPNEGO_E_SUCCESS
11524bff34e3Sthurlow //          Failure - SPNEGO API Error code
11534bff34e3Sthurlow //
11544bff34e3Sthurlow // Comments :
11554bff34e3Sthurlow //    Checks that pbTokenData is pointing at the specified DER type.  If so,
11564bff34e3Sthurlow //    then we verify that lengths are proper and then fill out the
11574bff34e3Sthurlow //    SPNEGO_ELEMENT data structure.
11584bff34e3Sthurlow //
11594bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
11604bff34e3Sthurlow 
InitSpnegoTokenElementFromBasicType(unsigned char * pbTokenData,int nElementLength,unsigned char ucExpectedType,SPNEGO_ELEMENT_TYPE spnegoElementType,SPNEGO_ELEMENT * pSpnegoElement)11614bff34e3Sthurlow int InitSpnegoTokenElementFromBasicType( unsigned char* pbTokenData, int nElementLength,
11624bff34e3Sthurlow                                           unsigned char ucExpectedType,
11634bff34e3Sthurlow                                           SPNEGO_ELEMENT_TYPE spnegoElementType,
11644bff34e3Sthurlow                                           SPNEGO_ELEMENT* pSpnegoElement )
11654bff34e3Sthurlow {
11664bff34e3Sthurlow    int   nReturn = SPNEGO_E_UNEXPECTED_TYPE;
11674bff34e3Sthurlow    long  nLength = 0L;
11684bff34e3Sthurlow    long  nActualTokenLength = 0L;
11694bff34e3Sthurlow 
11704bff34e3Sthurlow    // The type BYTE must match our token data or something is badly wrong
11714bff34e3Sthurlow    if ( *pbTokenData == ucExpectedType )
11724bff34e3Sthurlow    {
11734bff34e3Sthurlow 
11744bff34e3Sthurlow       // Check that we are pointing at the specified type
11754bff34e3Sthurlow       if ( ( nReturn = ASNDerCheckToken( pbTokenData, ucExpectedType,
11764bff34e3Sthurlow                                           nElementLength, nElementLength,
11774bff34e3Sthurlow                                           &nLength, &nActualTokenLength ) )
11784bff34e3Sthurlow                                 == SPNEGO_E_SUCCESS )
11794bff34e3Sthurlow       {
11804bff34e3Sthurlow          // Adjust for this token
11814bff34e3Sthurlow          nElementLength -= nActualTokenLength;
11824bff34e3Sthurlow          pbTokenData += nActualTokenLength;
11834bff34e3Sthurlow 
11844bff34e3Sthurlow          // Initialize the element now
11854bff34e3Sthurlow          pSpnegoElement->eElementType = spnegoElementType;
11864bff34e3Sthurlow          pSpnegoElement->iElementPresent = SPNEGO_TOKEN_ELEMENT_AVAILABLE;
11874bff34e3Sthurlow          pSpnegoElement->type = ucExpectedType;
11884bff34e3Sthurlow          pSpnegoElement->nDatalength = nLength;
11894bff34e3Sthurlow          pSpnegoElement->pbData = pbTokenData;
11904bff34e3Sthurlow       }
11914bff34e3Sthurlow 
11924bff34e3Sthurlow    }  // IF type makes sense
11934bff34e3Sthurlow 
11944bff34e3Sthurlow    return nReturn;
11954bff34e3Sthurlow }
11964bff34e3Sthurlow 
11974bff34e3Sthurlow 
11984bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
11994bff34e3Sthurlow //
12004bff34e3Sthurlow // Function:
12014bff34e3Sthurlow //    InitSpnegoTokenElementFromOID
12024bff34e3Sthurlow //
12034bff34e3Sthurlow // Parameters:
12044bff34e3Sthurlow //    [in]  pbTokenData             -  Points to binary element data in
12054bff34e3Sthurlow //                                     a SPNEGO token.
12064bff34e3Sthurlow //    [in]  nElementLength          -  Length of the element
12074bff34e3Sthurlow //    [in]  spnegoElementType       -  Which element is this?
12084bff34e3Sthurlow //    [out] pSpnegoElement          -  Filled out with element data.
12094bff34e3Sthurlow //
12104bff34e3Sthurlow // Returns:
12114bff34e3Sthurlow //    int   Success - SPNEGO_E_SUCCESS
12124bff34e3Sthurlow //          Failure - SPNEGO API Error code
12134bff34e3Sthurlow //
12144bff34e3Sthurlow // Comments :
12154bff34e3Sthurlow //    Initializes a SpnegoElement from an OID - normally, this would have
12164bff34e3Sthurlow //    used the Basic Type function above, but since we do binary compares
12174bff34e3Sthurlow //    on the OIDs against the DER information as well as the OID, we need
12184bff34e3Sthurlow //    to account for that.
12194bff34e3Sthurlow //
12204bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
12214bff34e3Sthurlow 
InitSpnegoTokenElementFromOID(unsigned char * pbTokenData,int nElementLength,SPNEGO_ELEMENT_TYPE spnegoElementType,SPNEGO_ELEMENT * pSpnegoElement)12224bff34e3Sthurlow int InitSpnegoTokenElementFromOID( unsigned char* pbTokenData, int nElementLength,
12234bff34e3Sthurlow                                    SPNEGO_ELEMENT_TYPE spnegoElementType,
12244bff34e3Sthurlow                                    SPNEGO_ELEMENT* pSpnegoElement )
12254bff34e3Sthurlow {
12264bff34e3Sthurlow    int   nReturn = SPNEGO_E_UNEXPECTED_TYPE;
12274bff34e3Sthurlow    long  nLength = 0L;
12284bff34e3Sthurlow    long  nActualTokenLength = 0L;
12294bff34e3Sthurlow 
12304bff34e3Sthurlow    // The type BYTE must match our token data or something is badly wrong
12314bff34e3Sthurlow    if ( *pbTokenData == OID )
12324bff34e3Sthurlow    {
12334bff34e3Sthurlow 
12344bff34e3Sthurlow       // Check that we are pointing at an OID type
12354bff34e3Sthurlow       if ( ( nReturn = ASNDerCheckToken( pbTokenData, OID,
12364bff34e3Sthurlow                                           nElementLength, nElementLength,
12374bff34e3Sthurlow                                           &nLength, &nActualTokenLength ) )
12384bff34e3Sthurlow                                 == SPNEGO_E_SUCCESS )
12394bff34e3Sthurlow       {
12404bff34e3Sthurlow          // Don't adjust any values for this function
12414bff34e3Sthurlow 
12424bff34e3Sthurlow          // Initialize the element now
12434bff34e3Sthurlow          pSpnegoElement->eElementType = spnegoElementType;
12444bff34e3Sthurlow          pSpnegoElement->iElementPresent = SPNEGO_TOKEN_ELEMENT_AVAILABLE;
12454bff34e3Sthurlow          pSpnegoElement->type = OID;
12464bff34e3Sthurlow          pSpnegoElement->nDatalength = nElementLength;
12474bff34e3Sthurlow          pSpnegoElement->pbData = pbTokenData;
12484bff34e3Sthurlow       }
12494bff34e3Sthurlow 
12504bff34e3Sthurlow    }  // IF type makes sense
12514bff34e3Sthurlow 
12524bff34e3Sthurlow    return nReturn;
12534bff34e3Sthurlow }
12544bff34e3Sthurlow 
12554bff34e3Sthurlow 
12564bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
12574bff34e3Sthurlow //
12584bff34e3Sthurlow // Function:
12594bff34e3Sthurlow //    InitSpnegoTokenElements
12604bff34e3Sthurlow //
12614bff34e3Sthurlow // Parameters:
12624bff34e3Sthurlow //    [in]  pSpnegoToken            -  Points to SPNEGO_TOKEN struct
12634bff34e3Sthurlow //    [in]  pbTokenData             -  Points to initial binary element
12644bff34e3Sthurlow //                                     data in a SPNEGO token.
12654bff34e3Sthurlow //    [in]  nRemainingTokenLength   -  Length remaining past header
12664bff34e3Sthurlow //
12674bff34e3Sthurlow // Returns:
12684bff34e3Sthurlow //    int   Success - SPNEGO_E_SUCCESS
12694bff34e3Sthurlow //          Failure - SPNEGO API Error code
12704bff34e3Sthurlow //
12714bff34e3Sthurlow // Comments :
12724bff34e3Sthurlow //    Interprets the data at pbTokenData based on the TokenType in
12734bff34e3Sthurlow //    pSpnegoToken.  Since some elements are optional (technically all are
12744bff34e3Sthurlow //    but the token becomes quite useless if this is so), we check if
12754bff34e3Sthurlow //    an element exists before filling out the element in the array.
12764bff34e3Sthurlow //
12774bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
12784bff34e3Sthurlow 
InitSpnegoTokenElements(SPNEGO_TOKEN * pSpnegoToken,unsigned char * pbTokenData,long nRemainingTokenLength)12794bff34e3Sthurlow int InitSpnegoTokenElements( SPNEGO_TOKEN* pSpnegoToken, unsigned char* pbTokenData,
12804bff34e3Sthurlow                            long nRemainingTokenLength  )
12814bff34e3Sthurlow {
12824bff34e3Sthurlow    //
12834bff34e3Sthurlow    // The following arrays contain the token identifiers for the elements
12844bff34e3Sthurlow    // comprising the actual token.  All values are optional, and there are
12854bff34e3Sthurlow    // no defaults.
12864bff34e3Sthurlow    //
12874bff34e3Sthurlow 
12884bff34e3Sthurlow    static unsigned char abNegTokenInitElements[] =
12894bff34e3Sthurlow       { SPNEGO_NEGINIT_ELEMENT_MECHTYPES, SPNEGO_NEGINIT_ELEMENT_REQFLAGS,
12904bff34e3Sthurlow          SPNEGO_NEGINIT_ELEMENT_MECHTOKEN, SPNEGO_NEGINIT_ELEMENT_MECHLISTMIC };
12914bff34e3Sthurlow 
12924bff34e3Sthurlow    static unsigned char abNegTokenTargElements[] =
12934bff34e3Sthurlow       { SPNEGO_NEGTARG_ELEMENT_NEGRESULT, SPNEGO_NEGTARG_ELEMENT_SUPPORTEDMECH,
12944bff34e3Sthurlow          SPNEGO_NEGTARG_ELEMENT_RESPONSETOKEN, SPNEGO_NEGTARG_ELEMENT_MECHLISTMIC };
12954bff34e3Sthurlow 
12964bff34e3Sthurlow    int   nReturn = SPNEGO_E_SUCCESS;
12974bff34e3Sthurlow    int   nCtr = 0L;
12984bff34e3Sthurlow    long  nElementLength = 0L;
12994bff34e3Sthurlow    long  nActualTokenLength = 0L;
13004bff34e3Sthurlow    unsigned char* pbElements = NULL;
13014bff34e3Sthurlow 
13024bff34e3Sthurlow    // Point to the correct array
13034bff34e3Sthurlow    switch( pSpnegoToken->ucTokenType )
13044bff34e3Sthurlow    {
13054bff34e3Sthurlow       case SPNEGO_TOKEN_INIT:
13064bff34e3Sthurlow       {
13074bff34e3Sthurlow          pbElements = abNegTokenInitElements;
13084bff34e3Sthurlow       }
13094bff34e3Sthurlow       break;
13104bff34e3Sthurlow 
13114bff34e3Sthurlow       case SPNEGO_TOKEN_TARG:
13124bff34e3Sthurlow       {
13134bff34e3Sthurlow          pbElements = abNegTokenTargElements;
13144bff34e3Sthurlow       }
13154bff34e3Sthurlow       break;
13164bff34e3Sthurlow 
13174bff34e3Sthurlow    }  // SWITCH tokentype
13184bff34e3Sthurlow 
13194bff34e3Sthurlow    //
13204bff34e3Sthurlow    // Enumerate the element arrays and look for the tokens at our current location
13214bff34e3Sthurlow    //
13224bff34e3Sthurlow 
13234bff34e3Sthurlow    for ( nCtr = 0L;
13244bff34e3Sthurlow          SPNEGO_E_SUCCESS == nReturn &&
13254bff34e3Sthurlow          nCtr < MAX_NUM_TOKEN_ELEMENTS &&
13264bff34e3Sthurlow          nRemainingTokenLength > 0L;
13274bff34e3Sthurlow          nCtr++ )
13284bff34e3Sthurlow    {
13294bff34e3Sthurlow 
13304bff34e3Sthurlow       // Check if the token exists
13314bff34e3Sthurlow       if ( ( nReturn = ASNDerCheckToken( pbTokenData, pbElements[nCtr],
13324bff34e3Sthurlow                                           0L, nRemainingTokenLength,
13334bff34e3Sthurlow                                           &nElementLength, &nActualTokenLength ) )
13344bff34e3Sthurlow                                 == SPNEGO_E_SUCCESS )
13354bff34e3Sthurlow       {
13364bff34e3Sthurlow 
13374bff34e3Sthurlow          // Token data should skip over the sequence token and then
13384bff34e3Sthurlow          // call the appropriate function to initialize the element
13394bff34e3Sthurlow          pbTokenData += nActualTokenLength;
13404bff34e3Sthurlow 
13414bff34e3Sthurlow          // Lengths in the elements should NOT go beyond the element
13424bff34e3Sthurlow          // length
13434bff34e3Sthurlow 
13444bff34e3Sthurlow          // Different tokens mean different elements
13454bff34e3Sthurlow          if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
13464bff34e3Sthurlow          {
13474bff34e3Sthurlow 
13484bff34e3Sthurlow             // Handle each element as appropriate
13494bff34e3Sthurlow             switch( pbElements[nCtr] )
13504bff34e3Sthurlow             {
13514bff34e3Sthurlow 
13524bff34e3Sthurlow                case SPNEGO_NEGINIT_ELEMENT_MECHTYPES:
13534bff34e3Sthurlow                {
13544bff34e3Sthurlow                   //
13554bff34e3Sthurlow                   // This is a Mech List that specifies which OIDs the
13564bff34e3Sthurlow                   // originator of the Init Token supports.
13574bff34e3Sthurlow                   //
13584bff34e3Sthurlow 
13594bff34e3Sthurlow                   nReturn = GetSpnegoInitTokenMechList( pbTokenData, nElementLength,
13604bff34e3Sthurlow                                                          &pSpnegoToken->aElementArray[nCtr] );
13614bff34e3Sthurlow 
13624bff34e3Sthurlow                }
13634bff34e3Sthurlow                break;
13644bff34e3Sthurlow 
13654bff34e3Sthurlow                case SPNEGO_NEGINIT_ELEMENT_REQFLAGS:
13664bff34e3Sthurlow                {
13674bff34e3Sthurlow                   //
13684bff34e3Sthurlow                   // This is a BITSTRING which specifies the flags that the receiver
13694bff34e3Sthurlow                   // pass to the gss_accept_sec_context() function.
13704bff34e3Sthurlow                   //
13714bff34e3Sthurlow 
13724bff34e3Sthurlow                   nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength,
13734bff34e3Sthurlow                                                                   BITSTRING, spnego_init_reqFlags,
13744bff34e3Sthurlow                                                                   &pSpnegoToken->aElementArray[nCtr] );
13754bff34e3Sthurlow                }
13764bff34e3Sthurlow                break;
13774bff34e3Sthurlow 
13784bff34e3Sthurlow                case SPNEGO_NEGINIT_ELEMENT_MECHTOKEN:
13794bff34e3Sthurlow                {
13804bff34e3Sthurlow                   //
13814bff34e3Sthurlow                   // This is an OCTETSTRING which contains a GSSAPI token corresponding
13824bff34e3Sthurlow                   // to the first OID in the MechList.
13834bff34e3Sthurlow                   //
13844bff34e3Sthurlow 
13854bff34e3Sthurlow                   nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength,
13864bff34e3Sthurlow                                                                   OCTETSTRING, spnego_init_mechToken,
13874bff34e3Sthurlow                                                                   &pSpnegoToken->aElementArray[nCtr] );
13884bff34e3Sthurlow                }
13894bff34e3Sthurlow                break;
13904bff34e3Sthurlow 
1391*12b65585SGordon Ross                case SPNEGO_NEGINIT_ELEMENT_MECHLISTMIC:  // xA3
13924bff34e3Sthurlow                {
13934bff34e3Sthurlow                   //
1394*12b65585SGordon Ross                   // Don't yet know if this is a negTokenInit, or negTokenInit2.
1395*12b65585SGordon Ross                   // Unfortunately, both have the same type: SPNEGO_TOKEN_INIT
1396*12b65585SGordon Ross                   // If it's negTokenInit, this element should be an OCTETSTRING
1397*12b65585SGordon Ross                   // containing the MIC.  If it's a negTokenInit2, this element
1398*12b65585SGordon Ross                   // should be an SPNEGO_CONSTRUCTED_SEQUENCE containing the
1399*12b65585SGordon Ross                   // negHints (GENERALSTR, ignored)
14004bff34e3Sthurlow                   //
14014bff34e3Sthurlow 
14024bff34e3Sthurlow                   nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength,
14034bff34e3Sthurlow                                                                  OCTETSTRING, spnego_init_mechListMIC,
14044bff34e3Sthurlow                                                                  &pSpnegoToken->aElementArray[nCtr] );
14054bff34e3Sthurlow 
1406*12b65585SGordon Ross                   if (nReturn == SPNEGO_E_UNEXPECTED_TYPE) {
1407*12b65585SGordon Ross                      // This is really a negHints element.  Check the type and length,
1408*12b65585SGordon Ross                      // but otherwise just ignore it.
1409*12b65585SGordon Ross                      long  elen, tlen;
1410*12b65585SGordon Ross                      nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_CONSTRUCTED_SEQUENCE,
1411*12b65585SGordon Ross                                           nElementLength, nElementLength,
1412*12b65585SGordon Ross                                           &elen, &tlen );
1413*12b65585SGordon Ross                   }
14144bff34e3Sthurlow                }
14154bff34e3Sthurlow                break;
14164bff34e3Sthurlow 
14174bff34e3Sthurlow             }  // SWITCH Element
14184bff34e3Sthurlow          }
14194bff34e3Sthurlow          else
14204bff34e3Sthurlow          {
1421*12b65585SGordon Ross             /* pSpnegoToken->ucTokenType == SPNEGO_TOKEN_TARG */
14224bff34e3Sthurlow 
14234bff34e3Sthurlow             switch( pbElements[nCtr] )
14244bff34e3Sthurlow             {
14254bff34e3Sthurlow 
14264bff34e3Sthurlow                case SPNEGO_NEGTARG_ELEMENT_NEGRESULT:
14274bff34e3Sthurlow                {
14284bff34e3Sthurlow                   //
14294bff34e3Sthurlow                   // This is an ENUMERATION which specifies result of the last GSS
14304bff34e3Sthurlow                   // token negotiation call.
14314bff34e3Sthurlow                   //
14324bff34e3Sthurlow 
14334bff34e3Sthurlow                   nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength,
14344bff34e3Sthurlow                                                                   ENUMERATED, spnego_targ_negResult,
14354bff34e3Sthurlow                                                                   &pSpnegoToken->aElementArray[nCtr] );
14364bff34e3Sthurlow                }
14374bff34e3Sthurlow                break;
14384bff34e3Sthurlow 
14394bff34e3Sthurlow                case SPNEGO_NEGTARG_ELEMENT_SUPPORTEDMECH:
14404bff34e3Sthurlow                {
14414bff34e3Sthurlow                   //
14424bff34e3Sthurlow                   // This is an OID which specifies a supported mechanism.
14434bff34e3Sthurlow                   //
14444bff34e3Sthurlow 
14454bff34e3Sthurlow                   nReturn = InitSpnegoTokenElementFromOID( pbTokenData, nElementLength,
14464bff34e3Sthurlow                                                            spnego_targ_mechListMIC,
14474bff34e3Sthurlow                                                            &pSpnegoToken->aElementArray[nCtr] );
14484bff34e3Sthurlow                }
14494bff34e3Sthurlow                break;
14504bff34e3Sthurlow 
14514bff34e3Sthurlow                case SPNEGO_NEGTARG_ELEMENT_RESPONSETOKEN:
14524bff34e3Sthurlow                {
14534bff34e3Sthurlow                   //
14544bff34e3Sthurlow                   // This is an OCTETSTRING which specifies results of the last GSS
14554bff34e3Sthurlow                   // token negotiation call.
14564bff34e3Sthurlow                   //
14574bff34e3Sthurlow 
14584bff34e3Sthurlow                   nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength,
14594bff34e3Sthurlow                                                                   OCTETSTRING, spnego_targ_responseToken,
14604bff34e3Sthurlow                                                                   &pSpnegoToken->aElementArray[nCtr] );
14614bff34e3Sthurlow                }
14624bff34e3Sthurlow                break;
14634bff34e3Sthurlow 
14644bff34e3Sthurlow                case SPNEGO_NEGTARG_ELEMENT_MECHLISTMIC:
14654bff34e3Sthurlow                {
14664bff34e3Sthurlow                   //
1467*12b65585SGordon Ross                   // This is an OCTETSTRING, typically 16 bytes,
1468*12b65585SGordon Ross                   // which contains a message integrity BLOB.
14694bff34e3Sthurlow                   //
14704bff34e3Sthurlow 
14714bff34e3Sthurlow                   nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength,
14724bff34e3Sthurlow                                                                  OCTETSTRING, spnego_targ_mechListMIC,
14734bff34e3Sthurlow                                                                  &pSpnegoToken->aElementArray[nCtr] );
14744bff34e3Sthurlow                }
14754bff34e3Sthurlow                break;
14764bff34e3Sthurlow 
14774bff34e3Sthurlow             }  // SWITCH Element
14784bff34e3Sthurlow 
14794bff34e3Sthurlow          }  // ELSE !NegTokenInit
14804bff34e3Sthurlow 
14814bff34e3Sthurlow          // Account for the entire token and following data
14824bff34e3Sthurlow          nRemainingTokenLength -= ( nActualTokenLength + nElementLength );
14834bff34e3Sthurlow 
14844bff34e3Sthurlow          // Token data should skip past the element length now
14854bff34e3Sthurlow          pbTokenData += nElementLength;
14864bff34e3Sthurlow 
14874bff34e3Sthurlow       }  // IF Token found
14884bff34e3Sthurlow       else if ( SPNEGO_E_TOKEN_NOT_FOUND == nReturn )
14894bff34e3Sthurlow       {
14904bff34e3Sthurlow          // For now, this is a benign error (remember, all elements are optional, so
14914bff34e3Sthurlow          // if we don't find one, it's okay).
14924bff34e3Sthurlow 
14934bff34e3Sthurlow          nReturn = SPNEGO_E_SUCCESS;
14944bff34e3Sthurlow       }
14954bff34e3Sthurlow 
14964bff34e3Sthurlow    }  // FOR enum elements
14974bff34e3Sthurlow 
14984bff34e3Sthurlow    //
14994bff34e3Sthurlow    // We should always run down to 0 remaining bytes in the token.  If not, we've got
15004bff34e3Sthurlow    // a bad token.
15014bff34e3Sthurlow    //
15024bff34e3Sthurlow 
15034bff34e3Sthurlow    if ( SPNEGO_E_SUCCESS == nReturn && nRemainingTokenLength != 0L )
15044bff34e3Sthurlow    {
15054bff34e3Sthurlow       nReturn = SPNEGO_E_INVALID_TOKEN;
15064bff34e3Sthurlow    }
15074bff34e3Sthurlow 
15084bff34e3Sthurlow    return nReturn;
15094bff34e3Sthurlow }
15104bff34e3Sthurlow 
15114bff34e3Sthurlow 
15124bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
15134bff34e3Sthurlow //
15144bff34e3Sthurlow // Function:
15154bff34e3Sthurlow //    FindMechOIDInMechList
15164bff34e3Sthurlow //
15174bff34e3Sthurlow // Parameters:
15184bff34e3Sthurlow //    [in]  pSpnegoElement          -  SPNEGO_ELEMENT for MechList
15194bff34e3Sthurlow //    [in]  MechOID                 -  OID we're looking for.
15204bff34e3Sthurlow //    [out] piMechTypeIndex         -  Index in the list where OID was
15214bff34e3Sthurlow //                                     found
15224bff34e3Sthurlow //
15234bff34e3Sthurlow // Returns:
15244bff34e3Sthurlow //    int   Success - SPNEGO_E_SUCCESS
15254bff34e3Sthurlow //          Failure - SPNEGO API Error code
15264bff34e3Sthurlow //
15274bff34e3Sthurlow // Comments :
15284bff34e3Sthurlow //    Walks the MechList for MechOID.  When it is found, the index in the
15294bff34e3Sthurlow //    list is written to piMechTypeIndex.
15304bff34e3Sthurlow //
15314bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
15324bff34e3Sthurlow 
FindMechOIDInMechList(SPNEGO_ELEMENT * pSpnegoElement,SPNEGO_MECH_OID MechOID,int * piMechTypeIndex)15334bff34e3Sthurlow int FindMechOIDInMechList( SPNEGO_ELEMENT* pSpnegoElement, SPNEGO_MECH_OID MechOID,
15344bff34e3Sthurlow                           int * piMechTypeIndex )
15354bff34e3Sthurlow {
15364bff34e3Sthurlow    int   nReturn = SPNEGO_E_NOT_FOUND;
15374bff34e3Sthurlow    int   nCtr = 0;
15384bff34e3Sthurlow    long  nLength = 0L;
15394bff34e3Sthurlow    long  nBoundaryLength = pSpnegoElement->nDatalength;
15404bff34e3Sthurlow    unsigned char* pbMechListData = pSpnegoElement->pbData;
15414bff34e3Sthurlow 
15424bff34e3Sthurlow    while( SPNEGO_E_SUCCESS != nReturn && nBoundaryLength > 0L )
15434bff34e3Sthurlow    {
15444bff34e3Sthurlow 
15454bff34e3Sthurlow       // Use the helper function to check the OID
15464bff34e3Sthurlow       if ( ( nReturn = ASNDerCheckOID( pbMechListData, MechOID, nBoundaryLength, &nLength ) )
15474bff34e3Sthurlow                      == SPNEGO_E_SUCCESS )
15484bff34e3Sthurlow       {
15494bff34e3Sthurlow          *piMechTypeIndex = nCtr;
15504bff34e3Sthurlow       }
15514bff34e3Sthurlow 
15524bff34e3Sthurlow       // Adjust for the current OID
15534bff34e3Sthurlow       pbMechListData += nLength;
15544bff34e3Sthurlow       nBoundaryLength -= nLength;
15554bff34e3Sthurlow       nCtr++;
15564bff34e3Sthurlow 
15574bff34e3Sthurlow    }  // WHILE enuming OIDs
15584bff34e3Sthurlow 
15594bff34e3Sthurlow    return nReturn;
15604bff34e3Sthurlow 
15614bff34e3Sthurlow }
15624bff34e3Sthurlow 
15634bff34e3Sthurlow 
15644bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
15654bff34e3Sthurlow //
15664bff34e3Sthurlow // Function:
15674bff34e3Sthurlow //    ValidateMechList
15684bff34e3Sthurlow //
15694bff34e3Sthurlow // Parameters:
15704bff34e3Sthurlow //    [in]  pbMechListData          -  Pointer to binary MechList data
15714bff34e3Sthurlow //    [in]  nBoundaryLength         -  Length we must not exceed
15724bff34e3Sthurlow //
15734bff34e3Sthurlow // Returns:
15744bff34e3Sthurlow //    int   Success - SPNEGO_E_SUCCESS
15754bff34e3Sthurlow //          Failure - SPNEGO API Error code
15764bff34e3Sthurlow //
15774bff34e3Sthurlow // Comments :
15784bff34e3Sthurlow //    Checks the data at pbMechListData to see if it looks like a MechList.
15794bff34e3Sthurlow //    As part of this, we walk the list and ensure that none of the OIDs
15804bff34e3Sthurlow //    have a length that takes us outside of nBoundaryLength.
15814bff34e3Sthurlow //
15824bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
15834bff34e3Sthurlow 
ValidateMechList(unsigned char * pbMechListData,long nBoundaryLength)15844bff34e3Sthurlow int ValidateMechList( unsigned char* pbMechListData, long nBoundaryLength )
15854bff34e3Sthurlow {
15864bff34e3Sthurlow    int   nReturn = SPNEGO_E_SUCCESS;
15874bff34e3Sthurlow    long  nLength = 0L;
15884bff34e3Sthurlow    long  nTokenLength = 0L;
15894bff34e3Sthurlow 
15904bff34e3Sthurlow    while( SPNEGO_E_SUCCESS == nReturn && nBoundaryLength > 0L )
15914bff34e3Sthurlow    {
15924bff34e3Sthurlow       // Verify that we have something that at least *looks* like an OID - in other
15934bff34e3Sthurlow       // words it has an OID identifier and specifies a length that doesn't go beyond
15944bff34e3Sthurlow       // the size of the list.
15954bff34e3Sthurlow       nReturn = ASNDerCheckToken( pbMechListData, OID, 0L, nBoundaryLength,
15964bff34e3Sthurlow                                   &nLength, &nTokenLength );
15974bff34e3Sthurlow 
15984bff34e3Sthurlow       // Adjust for the current OID
15994bff34e3Sthurlow       pbMechListData += ( nLength + nTokenLength );
16004bff34e3Sthurlow       nBoundaryLength -= ( nLength + nTokenLength );
16014bff34e3Sthurlow 
16024bff34e3Sthurlow    }  // WHILE enuming OIDs
16034bff34e3Sthurlow 
16044bff34e3Sthurlow    return nReturn;
16054bff34e3Sthurlow 
16064bff34e3Sthurlow }
16074bff34e3Sthurlow 
16084bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
16094bff34e3Sthurlow //
16104bff34e3Sthurlow // Function:
16114bff34e3Sthurlow //    IsValidMechOid
16124bff34e3Sthurlow //
16134bff34e3Sthurlow // Parameters:
16144bff34e3Sthurlow //    [in]  mechOid  -  mechOID id enumeration
16154bff34e3Sthurlow //
16164bff34e3Sthurlow // Returns:
16174bff34e3Sthurlow //    int   Success - 1
16184bff34e3Sthurlow //          Failure - 0
16194bff34e3Sthurlow //
16204bff34e3Sthurlow // Comments :
16214bff34e3Sthurlow //    Checks for a valid mechOid value.
16224bff34e3Sthurlow //
16234bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
16244bff34e3Sthurlow 
IsValidMechOid(SPNEGO_MECH_OID mechOid)16254bff34e3Sthurlow int IsValidMechOid( SPNEGO_MECH_OID mechOid )
16264bff34e3Sthurlow {
16274bff34e3Sthurlow    return ( mechOid >= spnego_mech_oid_Kerberos_V5_Legacy &&
1628613a2f6bSGordon Ross             mechOid <= spnego_mech_oid_NTLMSSP );
16294bff34e3Sthurlow }
16304bff34e3Sthurlow 
16314bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
16324bff34e3Sthurlow //
16334bff34e3Sthurlow // Function:
16344bff34e3Sthurlow //    IsValidContextFlags
16354bff34e3Sthurlow //
16364bff34e3Sthurlow // Parameters:
16374bff34e3Sthurlow //    [in]  ucContextFlags -  ContextFlags value
16384bff34e3Sthurlow //
16394bff34e3Sthurlow // Returns:
16404bff34e3Sthurlow //    int   Success - 1
16414bff34e3Sthurlow //          Failure - 0
16424bff34e3Sthurlow //
16434bff34e3Sthurlow // Comments :
16444bff34e3Sthurlow //    Checks for a valid ContextFlags value.
16454bff34e3Sthurlow //
16464bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
16474bff34e3Sthurlow 
IsValidContextFlags(unsigned char ucContextFlags)16484bff34e3Sthurlow int IsValidContextFlags( unsigned char ucContextFlags )
16494bff34e3Sthurlow {
16504bff34e3Sthurlow    // Mask out our valid bits.  If there is anything leftover, this
16514bff34e3Sthurlow    // is not a valid value for Context Flags
16524bff34e3Sthurlow    return ( ( ucContextFlags & ~SPNEGO_NEGINIT_CONTEXT_MASK ) == 0 );
16534bff34e3Sthurlow }
16544bff34e3Sthurlow 
16554bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
16564bff34e3Sthurlow //
16574bff34e3Sthurlow // Function:
16584bff34e3Sthurlow //    IsValidNegResult
16594bff34e3Sthurlow //
16604bff34e3Sthurlow // Parameters:
16614bff34e3Sthurlow //    [in]  negResult   -  NegResult value
16624bff34e3Sthurlow //
16634bff34e3Sthurlow // Returns:
16644bff34e3Sthurlow //    int   Success - 1
16654bff34e3Sthurlow //          Failure - 0
16664bff34e3Sthurlow //
16674bff34e3Sthurlow // Comments :
16684bff34e3Sthurlow //    Checks for a valid NegResult value.
16694bff34e3Sthurlow //
16704bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
16714bff34e3Sthurlow 
IsValidNegResult(SPNEGO_NEGRESULT negResult)16724bff34e3Sthurlow int IsValidNegResult( SPNEGO_NEGRESULT negResult )
16734bff34e3Sthurlow {
16744bff34e3Sthurlow    return ( negResult >= spnego_negresult_success &&
16754bff34e3Sthurlow             negResult <= spnego_negresult_rejected );
16764bff34e3Sthurlow }
16774bff34e3Sthurlow 
16784bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
16794bff34e3Sthurlow //
16804bff34e3Sthurlow // Function:
16814bff34e3Sthurlow //    IsValidSpnegoToken
16824bff34e3Sthurlow //
16834bff34e3Sthurlow // Parameters:
16844bff34e3Sthurlow //    [in]  pSpnegoToken   -  Points to SPNEGO_TOKEN data structure
16854bff34e3Sthurlow //
16864bff34e3Sthurlow // Returns:
16874bff34e3Sthurlow //    int   Success - 1
16884bff34e3Sthurlow //          Failure - 0
16894bff34e3Sthurlow //
16904bff34e3Sthurlow // Comments :
16914bff34e3Sthurlow //    Performs simple heuristic on location pointed to by pSpnegoToken.
16924bff34e3Sthurlow //
16934bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
16944bff34e3Sthurlow 
IsValidSpnegoToken(SPNEGO_TOKEN * pSpnegoToken)16954bff34e3Sthurlow int IsValidSpnegoToken( SPNEGO_TOKEN* pSpnegoToken )
16964bff34e3Sthurlow {
16974bff34e3Sthurlow    int   nReturn = 0;
16984bff34e3Sthurlow 
16994bff34e3Sthurlow    // Parameter should be non-NULL
17004bff34e3Sthurlow    if ( NULL != pSpnegoToken )
17014bff34e3Sthurlow    {
17024bff34e3Sthurlow       // Length should be at least the size defined in the header
17034bff34e3Sthurlow       if ( pSpnegoToken->nStructSize >= SPNEGO_TOKEN_SIZE )
17044bff34e3Sthurlow       {
17054bff34e3Sthurlow          // Number of elements should be >= our maximum - if it's greater, that's
17064bff34e3Sthurlow          // okay, since we'll only be accessing the elements up to MAX_NUM_TOKEN_ELEMENTS
17074bff34e3Sthurlow          if ( pSpnegoToken->nNumElements >= MAX_NUM_TOKEN_ELEMENTS )
17084bff34e3Sthurlow          {
17094bff34e3Sthurlow             // Check for proper token type
17104bff34e3Sthurlow             if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType ||
17114bff34e3Sthurlow                SPNEGO_TOKEN_TARG == pSpnegoToken->ucTokenType )
17124bff34e3Sthurlow             {
17134bff34e3Sthurlow                nReturn = 1;
17144bff34e3Sthurlow             }
17154bff34e3Sthurlow          }
17164bff34e3Sthurlow 
17174bff34e3Sthurlow       }  // IF struct size makes sense
17184bff34e3Sthurlow 
17194bff34e3Sthurlow    }  // IF non-NULL spnego Token
17204bff34e3Sthurlow 
17214bff34e3Sthurlow    return nReturn;
17224bff34e3Sthurlow }
17234bff34e3Sthurlow 
17244bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
17254bff34e3Sthurlow //
17264bff34e3Sthurlow // Function:
17274bff34e3Sthurlow //    IsValidSpnegoElement
17284bff34e3Sthurlow //
17294bff34e3Sthurlow // Parameters:
17304bff34e3Sthurlow //    [in]  pSpnegoToken   -  Points to SPNEGO_TOKEN data structure
17314bff34e3Sthurlow //    [in]  spnegoElement  -  spnegoElement Type from enumeration
17324bff34e3Sthurlow //
17334bff34e3Sthurlow // Returns:
17344bff34e3Sthurlow //    int   Success - 1
17354bff34e3Sthurlow //          Failure - 0
17364bff34e3Sthurlow //
17374bff34e3Sthurlow // Comments :
17384bff34e3Sthurlow //    Checks that spnegoElement has a valid value and is appropriate for
17394bff34e3Sthurlow //    the SPNEGO token encapsulated by pSpnegoToken.
17404bff34e3Sthurlow //
17414bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
17424bff34e3Sthurlow 
IsValidSpnegoElement(SPNEGO_TOKEN * pSpnegoToken,SPNEGO_ELEMENT_TYPE spnegoElement)17434bff34e3Sthurlow int IsValidSpnegoElement( SPNEGO_TOKEN* pSpnegoToken,SPNEGO_ELEMENT_TYPE spnegoElement )
17444bff34e3Sthurlow {
17454bff34e3Sthurlow    int   nReturn = 0;
17464bff34e3Sthurlow 
17474bff34e3Sthurlow    // Check boundaries
17484bff34e3Sthurlow    if ( spnegoElement > spnego_element_min &&
17494bff34e3Sthurlow       spnegoElement < spnego_element_max )
17504bff34e3Sthurlow    {
17514bff34e3Sthurlow 
17524bff34e3Sthurlow       // Check for appropriateness to token type
17534bff34e3Sthurlow       if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
17544bff34e3Sthurlow       {
17554bff34e3Sthurlow          nReturn = ( spnegoElement >= spnego_init_mechtypes &&
17564bff34e3Sthurlow                      spnegoElement <= spnego_init_mechListMIC );
17574bff34e3Sthurlow       }
17584bff34e3Sthurlow       else
17594bff34e3Sthurlow       {
17604bff34e3Sthurlow          nReturn = ( spnegoElement >= spnego_targ_negResult &&
17614bff34e3Sthurlow                      spnegoElement <= spnego_targ_mechListMIC );
17624bff34e3Sthurlow       }
17634bff34e3Sthurlow 
17644bff34e3Sthurlow    }  // IF boundary conditions are met
17654bff34e3Sthurlow 
17664bff34e3Sthurlow    return nReturn;
17674bff34e3Sthurlow }
17684bff34e3Sthurlow 
17694bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
17704bff34e3Sthurlow //
17714bff34e3Sthurlow // Function:
17724bff34e3Sthurlow //    CalculateElementArrayIndex
17734bff34e3Sthurlow //
17744bff34e3Sthurlow // Parameters:
17754bff34e3Sthurlow //    [in]  pSpnegoToken   -  Points to SPNEGO_TOKEN data structure
17764bff34e3Sthurlow //    [in]  spnegoElement  -  spnegoElement Type from enumeration
17774bff34e3Sthurlow //
17784bff34e3Sthurlow // Returns:
17794bff34e3Sthurlow //    int   index in the SPNEGO_TOKEN element array that the element can
17804bff34e3Sthurlow //          can be found
17814bff34e3Sthurlow //
17824bff34e3Sthurlow // Comments :
17834bff34e3Sthurlow //    Based on the Token Type, calculates the index in the element array
17844bff34e3Sthurlow //    at which the specified element can be found.
17854bff34e3Sthurlow //
17864bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
17874bff34e3Sthurlow 
CalculateElementArrayIndex(SPNEGO_TOKEN * pSpnegoToken,SPNEGO_ELEMENT_TYPE spnegoElement)17884bff34e3Sthurlow int CalculateElementArrayIndex( SPNEGO_TOKEN* pSpnegoToken,SPNEGO_ELEMENT_TYPE spnegoElement )
17894bff34e3Sthurlow {
17904bff34e3Sthurlow    int   nReturn = 0;
17914bff34e3Sthurlow 
17924bff34e3Sthurlow    // Offset is difference between value and initial element identifier
17934bff34e3Sthurlow    // (these differ based on ucTokenType)
17944bff34e3Sthurlow 
17954bff34e3Sthurlow    if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
17964bff34e3Sthurlow    {
17974bff34e3Sthurlow       nReturn = spnegoElement - spnego_init_mechtypes;
17984bff34e3Sthurlow    }
17994bff34e3Sthurlow    else
18004bff34e3Sthurlow    {
18014bff34e3Sthurlow       nReturn = spnegoElement - spnego_targ_negResult;
18024bff34e3Sthurlow    }
18034bff34e3Sthurlow 
18044bff34e3Sthurlow    return nReturn;
18054bff34e3Sthurlow }
18064bff34e3Sthurlow 
18074bff34e3Sthurlow /////////////////////////////////////////////////////////////////////////////
18084bff34e3Sthurlow //
18094bff34e3Sthurlow // Function:
18104bff34e3Sthurlow //    InitTokenFromBinary
18114bff34e3Sthurlow //
18124bff34e3Sthurlow // Parameters:
18134bff34e3Sthurlow //    [in]  ucCopyData     -  Flag indicating if data should be copied
18144bff34e3Sthurlow //    [in]  ulFlags        -  Flags value for structure
18154bff34e3Sthurlow //    [in]  pnTokenData    -  Binary Token Data
18164bff34e3Sthurlow //    [in]  ulLength       -  Length of the data
18174bff34e3Sthurlow //    [out] ppSpnegoToken  -  Pointer to call allocated SPNEGO Token
18184bff34e3Sthurlow //                            data structure
18194bff34e3Sthurlow //
18204bff34e3Sthurlow // Returns:
18214bff34e3Sthurlow //    int   Success - SPNEGO_E_SUCCESS
18224bff34e3Sthurlow //          Failure - SPNEGO API Error code
18234bff34e3Sthurlow //
18244bff34e3Sthurlow // Comments :
18254bff34e3Sthurlow //    Allocates a SPNEGO_TOKEN data structure and fills it out as
18264bff34e3Sthurlow //    appropriate based in the flags passed into the function.
18274bff34e3Sthurlow //
18284bff34e3Sthurlow ////////////////////////////////////////////////////////////////////////////
18294bff34e3Sthurlow 
18304bff34e3Sthurlow 
18314bff34e3Sthurlow // Initializes SPNEGO_TOKEN structure from DER encoded binary data
InitTokenFromBinary(unsigned char ucCopyData,unsigned long ulFlags,unsigned char * pbTokenData,unsigned long ulLength,SPNEGO_TOKEN ** ppSpnegoToken)18324bff34e3Sthurlow int InitTokenFromBinary( unsigned char ucCopyData, unsigned long ulFlags,
18334bff34e3Sthurlow                         unsigned char* pbTokenData, unsigned long ulLength,
18344bff34e3Sthurlow                         SPNEGO_TOKEN** ppSpnegoToken )
18354bff34e3Sthurlow {
18364bff34e3Sthurlow    int            nReturn = SPNEGO_E_INVALID_PARAMETER;
18374bff34e3Sthurlow    SPNEGO_TOKEN*  pSpnegoToken = NULL;
18384bff34e3Sthurlow    unsigned char* pbFirstElement = NULL;
18394bff34e3Sthurlow    long           nTokenLength = 0L;
18404bff34e3Sthurlow    long           nRemainingTokenLength = 0L;
18414bff34e3Sthurlow 
18424bff34e3Sthurlow    // Basic Parameter Validation
18434bff34e3Sthurlow 
18444bff34e3Sthurlow    if (  NULL != pbTokenData &&
18454bff34e3Sthurlow          NULL != ppSpnegoToken &&
18464bff34e3Sthurlow          0L != ulLength )
18474bff34e3Sthurlow    {
18484bff34e3Sthurlow 
18494bff34e3Sthurlow       //
18504bff34e3Sthurlow       // Allocate the empty token, then initialize the data structure.
18514bff34e3Sthurlow       //
18524bff34e3Sthurlow 
18534bff34e3Sthurlow       pSpnegoToken = AllocEmptySpnegoToken( ucCopyData, ulFlags, pbTokenData, ulLength );
18544bff34e3Sthurlow 
18554bff34e3Sthurlow       if ( NULL != pSpnegoToken )
18564bff34e3Sthurlow       {
18574bff34e3Sthurlow 
18584bff34e3Sthurlow          // Copy the binary data locally
18594bff34e3Sthurlow 
18604bff34e3Sthurlow 
18614bff34e3Sthurlow          // Initialize the token type
18624bff34e3Sthurlow          if ( ( nReturn = InitSpnegoTokenType( pSpnegoToken, &nTokenLength,
18634bff34e3Sthurlow                                                 &nRemainingTokenLength, &pbFirstElement ) )
18644bff34e3Sthurlow                         == SPNEGO_E_SUCCESS )
18654bff34e3Sthurlow          {
18664bff34e3Sthurlow 
18674bff34e3Sthurlow             // Initialize the element array
18684bff34e3Sthurlow             if ( ( nReturn = InitSpnegoTokenElements( pSpnegoToken, pbFirstElement,
18694bff34e3Sthurlow                                                       nRemainingTokenLength ) )
18704bff34e3Sthurlow                            == SPNEGO_E_SUCCESS )
18714bff34e3Sthurlow             {
18724bff34e3Sthurlow                *ppSpnegoToken = pSpnegoToken;
18734bff34e3Sthurlow             }
18744bff34e3Sthurlow 
18754bff34e3Sthurlow          }  // IF Init Token Type
18764bff34e3Sthurlow 
18774bff34e3Sthurlow          // Cleanup on error condition
18784bff34e3Sthurlow          if ( SPNEGO_E_SUCCESS != nReturn )
18794bff34e3Sthurlow          {
18804bff34e3Sthurlow             spnegoFreeData( pSpnegoToken );
18814bff34e3Sthurlow          }
18824bff34e3Sthurlow 
18834bff34e3Sthurlow       }
18844bff34e3Sthurlow       else
18854bff34e3Sthurlow       {
18864bff34e3Sthurlow          nReturn = SPNEGO_E_OUT_OF_MEMORY;
18874bff34e3Sthurlow       }
18884bff34e3Sthurlow 
18894bff34e3Sthurlow    }  // IF Valid parameters
18904bff34e3Sthurlow 
18914bff34e3Sthurlow 
18924bff34e3Sthurlow    return nReturn;
18934bff34e3Sthurlow }
1894