xref: /onnv-gate/usr/src/lib/libsmbfs/smb/spnegoparse.c (revision 10023:71bf38dba3d6)
16007Sthurlow // Copyright (C) 2002 Microsoft Corporation
26007Sthurlow // All rights reserved.
36007Sthurlow //
46007Sthurlow // THIS CODE AND INFORMATION IS PROVIDED "AS IS"
56007Sthurlow // WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
66007Sthurlow // OR IMPLIED, INCLUDING BUT NOT LIMITED
76007Sthurlow // TO THE IMPLIED WARRANTIES OF MERCHANTIBILITY
86007Sthurlow // AND/OR FITNESS FOR A PARTICULAR PURPOSE.
96007Sthurlow //
106007Sthurlow // Date    - 10/08/2002
116007Sthurlow // Author  - Sanj Surati
126007Sthurlow 
136007Sthurlow /////////////////////////////////////////////////////////////
146007Sthurlow //
156007Sthurlow // SPNEGOPARSE.C
166007Sthurlow //
176007Sthurlow // SPNEGO Token Handler Source File
186007Sthurlow //
196007Sthurlow // Contains implementation of SPNEGO Token parsing functions.
206007Sthurlow //
216007Sthurlow /////////////////////////////////////////////////////////////
226007Sthurlow 
236007Sthurlow #include <stdlib.h>
246007Sthurlow #include <stdio.h>
256007Sthurlow #include <memory.h>
266007Sthurlow #include "spnego.h"
276007Sthurlow #include "derparse.h"
286007Sthurlow #include "spnegoparse.h"
296007Sthurlow 
306007Sthurlow //
316007Sthurlow // Defined in DERPARSE.C
326007Sthurlow //
336007Sthurlow 
346007Sthurlow extern MECH_OID g_stcMechOIDList [];
356007Sthurlow 
366007Sthurlow /**********************************************************************/
376007Sthurlow /**                                                                  **/
386007Sthurlow /**                                                                  **/
396007Sthurlow /**                                                                  **/
406007Sthurlow /**                                                                  **/
416007Sthurlow /**                 Local SPNEGO Helper definitions                  **/
426007Sthurlow /**                                                                  **/
436007Sthurlow /**                                                                  **/
446007Sthurlow /**                                                                  **/
456007Sthurlow /**                                                                  **/
466007Sthurlow /**********************************************************************/
476007Sthurlow 
486007Sthurlow 
496007Sthurlow /////////////////////////////////////////////////////////////////////////////
506007Sthurlow //
516007Sthurlow // Function:
526007Sthurlow //    CalculateMinSpnegoInitTokenSize
536007Sthurlow //
546007Sthurlow // Parameters:
556007Sthurlow //    [in]  nMechTokenLength        -  Length of the MechToken Element
566007Sthurlow //    [in]  nMechListMICLength      -  Length of the MechListMIC Element
576007Sthurlow //    [in]  mechOID                 -  OID for MechList
586007Sthurlow //    [in]  nReqFlagsAvailable      -  Is ContextFlags element available
596007Sthurlow //    [out] pnTokenSize             -  Filled out with total size of token
606007Sthurlow //    [out] pnInternalTokenLength   -  Filled out with length minus length
616007Sthurlow //                                     for initial token.
626007Sthurlow //
636007Sthurlow // Returns:
646007Sthurlow //    int   Success - SPNEGO_E_SUCCESS
656007Sthurlow //          Failure - SPNEGO API Error code
666007Sthurlow //
676007Sthurlow // Comments :
686007Sthurlow //    Calculates the required length for a SPNEGO NegTokenInit token based
696007Sthurlow //    on the supplied variable length values and which elements are present.
706007Sthurlow //    Note that because the lengths can be represented by an arbitrary
716007Sthurlow //    number of bytes in DER encodings, we actually calculate the lengths
726007Sthurlow //    backwards, so we always know how many bytes we will potentially be
736007Sthurlow //    writing out.
746007Sthurlow //
756007Sthurlow ////////////////////////////////////////////////////////////////////////////
766007Sthurlow 
CalculateMinSpnegoInitTokenSize(long nMechTokenLength,long nMechListMICLength,SPNEGO_MECH_OID mechOid,int nReqFlagsAvailable,long * pnTokenSize,long * pnInternalTokenLength)776007Sthurlow int CalculateMinSpnegoInitTokenSize( long nMechTokenLength,
786007Sthurlow                                  long nMechListMICLength, SPNEGO_MECH_OID mechOid,
796007Sthurlow                                  int nReqFlagsAvailable, long* pnTokenSize,
806007Sthurlow                                  long* pnInternalTokenLength )
816007Sthurlow {
826007Sthurlow    int   nReturn = SPNEGO_E_INVALID_LENGTH;
836007Sthurlow 
846007Sthurlow    // Start at 0.
856007Sthurlow    long  nTotalLength = 0;
866007Sthurlow    long  nTempLength= 0L;
876007Sthurlow 
886007Sthurlow    // We will calculate this by walking the token backwards
896007Sthurlow 
906007Sthurlow    // Start with MIC Element
916007Sthurlow    if ( nMechListMICLength > 0L )
926007Sthurlow    {
936007Sthurlow       nTempLength = ASNDerCalcElementLength( nMechListMICLength, NULL );
946007Sthurlow 
956007Sthurlow       // Check for rollover error
966007Sthurlow       if ( nTempLength < nMechListMICLength )
976007Sthurlow       {
986007Sthurlow          goto xEndTokenInitLength;
996007Sthurlow       }
1006007Sthurlow 
1016007Sthurlow       nTotalLength += nTempLength;
1026007Sthurlow    }
1036007Sthurlow 
1046007Sthurlow    // Next is the MechToken
1056007Sthurlow    if ( nMechTokenLength > 0L )
1066007Sthurlow    {
1076007Sthurlow       nTempLength += ASNDerCalcElementLength( nMechTokenLength, NULL );
1086007Sthurlow 
1096007Sthurlow       // Check for rollover error
1106007Sthurlow       if ( nTempLength < nTotalLength )
1116007Sthurlow       {
1126007Sthurlow          goto xEndTokenInitLength;
1136007Sthurlow       }
1146007Sthurlow 
1156007Sthurlow       nTotalLength = nTempLength;
1166007Sthurlow    }
1176007Sthurlow 
1186007Sthurlow    // Next is the ReqFlags
1196007Sthurlow    if ( nReqFlagsAvailable )
1206007Sthurlow    {
1216007Sthurlow       nTempLength += ASNDerCalcElementLength( SPNEGO_NEGINIT_MAXLEN_REQFLAGS, NULL );
1226007Sthurlow 
1236007Sthurlow       // Check for rollover error
1246007Sthurlow       if ( nTempLength < nTotalLength )
1256007Sthurlow       {
1266007Sthurlow          goto xEndTokenInitLength;
1276007Sthurlow       }
1286007Sthurlow 
1296007Sthurlow       nTotalLength = nTempLength;
1306007Sthurlow    }
1316007Sthurlow 
1326007Sthurlow    // Next is the MechList - This is REQUIRED
1336007Sthurlow    nTempLength += ASNDerCalcMechListLength( mechOid, NULL );
1346007Sthurlow 
1356007Sthurlow    // Check for rollover error
1366007Sthurlow    if ( nTempLength < nTotalLength )
1376007Sthurlow    {
1386007Sthurlow       goto xEndTokenInitLength;
1396007Sthurlow    }
1406007Sthurlow 
1416007Sthurlow    nTotalLength = nTempLength;
1426007Sthurlow 
1436007Sthurlow    // Following four fields are the basic header tokens
1446007Sthurlow 
1456007Sthurlow    // Sequence Token
1466007Sthurlow    nTempLength += ASNDerCalcTokenLength( nTotalLength, 0L );
1476007Sthurlow 
1486007Sthurlow    // Check for rollover error
1496007Sthurlow    if ( nTempLength < nTotalLength )
1506007Sthurlow    {
1516007Sthurlow       goto xEndTokenInitLength;
1526007Sthurlow    }
1536007Sthurlow 
1546007Sthurlow    nTotalLength = nTempLength;
1556007Sthurlow 
1566007Sthurlow    // Neg Token Identifier Token
1576007Sthurlow    nTempLength += ASNDerCalcTokenLength( nTotalLength, 0L );
1586007Sthurlow 
1596007Sthurlow    // Check for rollover error
1606007Sthurlow    if ( nTempLength < nTotalLength )
1616007Sthurlow    {
1626007Sthurlow       goto xEndTokenInitLength;
1636007Sthurlow    }
1646007Sthurlow 
1656007Sthurlow    nTotalLength = nTempLength;
1666007Sthurlow 
1676007Sthurlow    // SPNEGO OID Token
1686007Sthurlow    nTempLength += g_stcMechOIDList[spnego_mech_oid_Spnego].iLen;
1696007Sthurlow 
1706007Sthurlow    // Check for rollover error
1716007Sthurlow    if ( nTempLength < nTotalLength )
1726007Sthurlow    {
1736007Sthurlow       goto xEndTokenInitLength;
1746007Sthurlow    }
1756007Sthurlow 
1766007Sthurlow    nTotalLength = nTempLength;
1776007Sthurlow 
1786007Sthurlow    // App Constructed Token
1796007Sthurlow    nTempLength += ASNDerCalcTokenLength( nTotalLength, 0L );
1806007Sthurlow 
1816007Sthurlow    // Check for rollover error
1826007Sthurlow    if ( nTempLength < nTotalLength )
1836007Sthurlow    {
1846007Sthurlow       goto xEndTokenInitLength;
1856007Sthurlow    }
1866007Sthurlow 
1876007Sthurlow    // The internal length doesn't include the number of bytes
1886007Sthurlow    // for the initial token
1896007Sthurlow    *pnInternalTokenLength = nTotalLength;
1906007Sthurlow    nTotalLength = nTempLength;
1916007Sthurlow 
1926007Sthurlow    // We're done
1936007Sthurlow    *pnTokenSize = nTotalLength;
1946007Sthurlow    nReturn = SPNEGO_E_SUCCESS;
1956007Sthurlow 
1966007Sthurlow xEndTokenInitLength:
1976007Sthurlow 
1986007Sthurlow    return nReturn;
1996007Sthurlow 
2006007Sthurlow }
2016007Sthurlow 
2026007Sthurlow /////////////////////////////////////////////////////////////////////////////
2036007Sthurlow //
2046007Sthurlow // Function:
2056007Sthurlow //    CreateSpnegoInitToken
2066007Sthurlow //
2076007Sthurlow // Parameters:
2086007Sthurlow //    [in]  MechType                -  OID in MechList
2096007Sthurlow //    [in]  ucContextFlags          -  ContextFlags value
2106007Sthurlow //    [in]  pbMechToken             -  Mech Token Binary Data
2116007Sthurlow //    [in]  ulMechTokenLen          -  Length of Mech Token
2126007Sthurlow //    [in]  pbMechListMIC           -  MechListMIC Binary Data
2136007Sthurlow //    [in]  ulMechListMICn          -  Length of MechListMIC
2146007Sthurlow //    [out] pbTokenData             -  Buffer to write token into.
2156007Sthurlow //    [in]  nTokenLength            -  Length of pbTokenData buffer
2166007Sthurlow //    [in]  nInternalTokenLength    -  Length of full token without leading
2176007Sthurlow //                                     token bytes.
2186007Sthurlow //
2196007Sthurlow // Returns:
2206007Sthurlow //    int   Success - SPNEGO_E_SUCCESS
2216007Sthurlow //          Failure - SPNEGO API Error code
2226007Sthurlow //
2236007Sthurlow // Comments :
2246007Sthurlow //    Uses DER to fill out pbTokenData with a SPNEGO NegTokenInit Token
2256007Sthurlow //    Note that because the lengths can be represented by an arbitrary
2266007Sthurlow //    number of bytes in DER encodings, we actually calculate the lengths
2276007Sthurlow //    backwards, so we always know how many bytes we will potentially be
2286007Sthurlow //    writing out.
2296007Sthurlow //
2306007Sthurlow ////////////////////////////////////////////////////////////////////////////
2316007Sthurlow 
CreateSpnegoInitToken(SPNEGO_MECH_OID MechType,unsigned char ucContextFlags,unsigned char * pbMechToken,unsigned long ulMechTokenLen,unsigned char * pbMechListMIC,unsigned long ulMechListMICLen,unsigned char * pbTokenData,long nTokenLength,long nInternalTokenLength)2326007Sthurlow int CreateSpnegoInitToken( SPNEGO_MECH_OID MechType,
2336007Sthurlow           unsigned char ucContextFlags, unsigned char* pbMechToken,
2346007Sthurlow           unsigned long ulMechTokenLen, unsigned char* pbMechListMIC,
2356007Sthurlow           unsigned long ulMechListMICLen, unsigned char* pbTokenData,
2366007Sthurlow           long nTokenLength, long nInternalTokenLength )
2376007Sthurlow {
2386007Sthurlow    int   nReturn = SPNEGO_E_INVALID_LENGTH;
2396007Sthurlow 
2406007Sthurlow    // Start at 0.
2416007Sthurlow    long  nTempLength= 0L;
2426007Sthurlow    long  nTotalBytesWritten = 0L;
2436007Sthurlow    long  nInternalLength = 0L;
2446007Sthurlow 
2456007Sthurlow    unsigned char* pbWriteTokenData = pbTokenData + nTokenLength;
2466007Sthurlow 
2476007Sthurlow    // Temporary buffer to hold the REQ Flags as BIT String Data
2486007Sthurlow    unsigned char  abTempReqFlags[SPNEGO_NEGINIT_MAXLEN_REQFLAGS];
2496007Sthurlow 
2506007Sthurlow 
2516007Sthurlow    // We will write the token out backwards to properly handle the cases
2526007Sthurlow    // where the length bytes become adjustable
2536007Sthurlow 
2546007Sthurlow    // Start with MIC Element
2556007Sthurlow    if ( ulMechListMICLen > 0L )
2566007Sthurlow    {
2576007Sthurlow       nTempLength = ASNDerCalcElementLength( ulMechListMICLen, &nInternalLength );
2586007Sthurlow 
2596007Sthurlow       // Decrease the pbWriteTokenData, now we know the length and
2606007Sthurlow       // write it out.
2616007Sthurlow 
2626007Sthurlow       pbWriteTokenData -= nTempLength;
2636007Sthurlow       nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGINIT_ELEMENT_MECHLISTMIC,
2646007Sthurlow                               OCTETSTRING, pbMechListMIC, ulMechListMICLen );
2656007Sthurlow 
2666007Sthurlow       // Adjust Values and sanity check
2676007Sthurlow       nTotalBytesWritten += nTempLength;
2686007Sthurlow       nInternalTokenLength -= nTempLength;
2696007Sthurlow 
2706007Sthurlow       if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
2716007Sthurlow       {
2726007Sthurlow          goto xEndWriteNegTokenInit;
2736007Sthurlow       }
2746007Sthurlow 
2756007Sthurlow    }  // IF MechListMIC is present
2766007Sthurlow 
2776007Sthurlow    // Next is the MechToken
2786007Sthurlow    if ( ulMechTokenLen > 0L )
2796007Sthurlow    {
2806007Sthurlow       nTempLength = ASNDerCalcElementLength( ulMechTokenLen, &nInternalLength );
2816007Sthurlow 
2826007Sthurlow       // Decrease the pbWriteTokenData, now we know the length and
2836007Sthurlow       // write it out.
2846007Sthurlow       pbWriteTokenData -= nTempLength;
2856007Sthurlow       nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGINIT_ELEMENT_MECHTOKEN,
2866007Sthurlow                               OCTETSTRING, pbMechToken, ulMechTokenLen );
2876007Sthurlow       // Adjust Values and sanity check
2886007Sthurlow       nTotalBytesWritten += nTempLength;
2896007Sthurlow       nInternalTokenLength -= nTempLength;
2906007Sthurlow 
2916007Sthurlow       if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
2926007Sthurlow       {
2936007Sthurlow          goto xEndWriteNegTokenInit;
2946007Sthurlow       }
2956007Sthurlow 
2966007Sthurlow    }  // IF MechToken Length is present
2976007Sthurlow 
2986007Sthurlow    // Next is the ReqFlags
2996007Sthurlow    if ( ucContextFlags > 0L )
3006007Sthurlow    {
3016007Sthurlow 
3026007Sthurlow       nTempLength = ASNDerCalcElementLength( SPNEGO_NEGINIT_MAXLEN_REQFLAGS, &nInternalLength );
3036007Sthurlow 
3046007Sthurlow       // We need a byte that indicates how many bits difference between the number
3056007Sthurlow       // of bits used in final octet (we only have one) and the max (8)
3066007Sthurlow 
3076007Sthurlow       abTempReqFlags[0] = SPNEGO_NEGINIT_REQFLAGS_BITDIFF;
3086007Sthurlow       abTempReqFlags[1] = ucContextFlags;
3096007Sthurlow 
3106007Sthurlow       // Decrease the pbWriteTokenData, now we know the length and
3116007Sthurlow       // write it out.
3126007Sthurlow       pbWriteTokenData -= nTempLength;
3136007Sthurlow       nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGINIT_ELEMENT_REQFLAGS,
3146007Sthurlow                               BITSTRING, abTempReqFlags, SPNEGO_NEGINIT_MAXLEN_REQFLAGS );
3156007Sthurlow 
3166007Sthurlow       // Adjust Values and sanity check
3176007Sthurlow       nTotalBytesWritten += nTempLength;
3186007Sthurlow       nInternalTokenLength -= nTempLength;
3196007Sthurlow 
3206007Sthurlow       if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
3216007Sthurlow       {
3226007Sthurlow          goto xEndWriteNegTokenInit;
3236007Sthurlow       }
3246007Sthurlow 
3256007Sthurlow    }  // IF ContextFlags
3266007Sthurlow 
3276007Sthurlow    // Next is the MechList - This is REQUIRED
3286007Sthurlow    nTempLength = ASNDerCalcMechListLength( MechType, &nInternalLength );
3296007Sthurlow 
3306007Sthurlow    // Decrease the pbWriteTokenData, now we know the length and
3316007Sthurlow    // write it out.
3326007Sthurlow    pbWriteTokenData -= nTempLength;
3336007Sthurlow    nTempLength = ASNDerWriteMechList( pbWriteTokenData, MechType );
3346007Sthurlow 
3356007Sthurlow    // Adjust Values and sanity check
3366007Sthurlow    nTotalBytesWritten += nTempLength;
3376007Sthurlow    nInternalTokenLength -= nTempLength;
3386007Sthurlow 
3396007Sthurlow    if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
3406007Sthurlow    {
3416007Sthurlow       goto xEndWriteNegTokenInit;
3426007Sthurlow    }
3436007Sthurlow 
3446007Sthurlow    // The next tokens we're writing out reflect the total number of bytes
3456007Sthurlow    // we have actually written out.
3466007Sthurlow 
3476007Sthurlow    // Sequence Token
3486007Sthurlow    nTempLength = ASNDerCalcTokenLength( nTotalBytesWritten, 0L );
3496007Sthurlow 
3506007Sthurlow    // Decrease the pbWriteTokenData, now we know the length and
3516007Sthurlow    // write it out.
3526007Sthurlow    pbWriteTokenData -= nTempLength;
3536007Sthurlow    nTempLength = ASNDerWriteToken( pbWriteTokenData, SPNEGO_CONSTRUCTED_SEQUENCE,
3546007Sthurlow                                     NULL, nTotalBytesWritten );
3556007Sthurlow 
3566007Sthurlow    // Adjust Values and sanity check
3576007Sthurlow    nTotalBytesWritten += nTempLength;
3586007Sthurlow    nInternalTokenLength -= nTempLength;
3596007Sthurlow 
3606007Sthurlow    if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
3616007Sthurlow    {
3626007Sthurlow       goto xEndWriteNegTokenInit;
3636007Sthurlow    }
3646007Sthurlow 
3656007Sthurlow    // Neg Init Token Identifier Token
3666007Sthurlow    nTempLength = ASNDerCalcTokenLength( nTotalBytesWritten, 0L );
3676007Sthurlow 
3686007Sthurlow    // Decrease the pbWriteTokenData, now we know the length and
3696007Sthurlow    // write it out.
3706007Sthurlow    pbWriteTokenData -= nTempLength;
3716007Sthurlow    nTempLength = ASNDerWriteToken( pbWriteTokenData, SPNEGO_NEGINIT_TOKEN_IDENTIFIER,
3726007Sthurlow                                     NULL, nTotalBytesWritten );
3736007Sthurlow 
3746007Sthurlow    // Adjust Values and sanity check
3756007Sthurlow    nTotalBytesWritten += nTempLength;
3766007Sthurlow    nInternalTokenLength -= nTempLength;
3776007Sthurlow 
3786007Sthurlow    if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
3796007Sthurlow    {
3806007Sthurlow       goto xEndWriteNegTokenInit;
3816007Sthurlow    }
3826007Sthurlow 
3836007Sthurlow    // SPNEGO OID Token
3846007Sthurlow    nTempLength = g_stcMechOIDList[spnego_mech_oid_Spnego].iLen;
3856007Sthurlow 
3866007Sthurlow    // Decrease the pbWriteTokenData, now we know the length and
3876007Sthurlow    // write it out.
3886007Sthurlow    pbWriteTokenData -= nTempLength;
3896007Sthurlow    nTempLength = ASNDerWriteOID( pbWriteTokenData, spnego_mech_oid_Spnego );
3906007Sthurlow 
3916007Sthurlow    // Adjust Values and sanity check
3926007Sthurlow    nTotalBytesWritten += nTempLength;
3936007Sthurlow    nInternalTokenLength -= nTempLength;
3946007Sthurlow 
3956007Sthurlow    if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
3966007Sthurlow    {
3976007Sthurlow       goto xEndWriteNegTokenInit;
3986007Sthurlow    }
3996007Sthurlow 
4006007Sthurlow    // App Constructed Token
4016007Sthurlow    nTempLength = ASNDerCalcTokenLength( nTotalBytesWritten, 0L );
4026007Sthurlow 
4036007Sthurlow    // Decrease the pbWriteTokenData, now we know the length and
4046007Sthurlow    // write it out.
4056007Sthurlow    pbWriteTokenData -= nTempLength;
4066007Sthurlow    nTempLength = ASNDerWriteToken( pbWriteTokenData, SPNEGO_NEGINIT_APP_CONSTRUCT,
4076007Sthurlow                                     NULL, nTotalBytesWritten );
4086007Sthurlow 
4096007Sthurlow    // Adjust Values and sanity check
4106007Sthurlow    nTotalBytesWritten += nTempLength;
4116007Sthurlow 
4126007Sthurlow    // Don't adjust the internal token length here, it doesn't account
4136007Sthurlow    // the initial bytes written out (we really don't need to keep
4146007Sthurlow    // a running count here, but for debugging, it helps to be able
4156007Sthurlow    // to see the total number of bytes written out as well as the
4166007Sthurlow    // number of bytes left to write).
4176007Sthurlow 
4186007Sthurlow    if ( nTotalBytesWritten == nTokenLength && nInternalTokenLength == 0 &&
4196007Sthurlow          pbWriteTokenData == pbTokenData )
4206007Sthurlow    {
4216007Sthurlow       nReturn = SPNEGO_E_SUCCESS;
4226007Sthurlow    }
4236007Sthurlow 
4246007Sthurlow xEndWriteNegTokenInit:
4256007Sthurlow 
4266007Sthurlow    return nReturn;
4276007Sthurlow 
4286007Sthurlow }
4296007Sthurlow 
4306007Sthurlow /////////////////////////////////////////////////////////////////////////////
4316007Sthurlow //
4326007Sthurlow // Function:
4336007Sthurlow //    CalculateMinSpnegoTargTokenSize
4346007Sthurlow //
4356007Sthurlow // Parameters:
4366007Sthurlow //    [in]  MechType                -  Supported MechType
4376007Sthurlow //    [in]  spnegoNegResult         -  Neg Result
4386007Sthurlow //    [in]  nMechTokenLength        -  Length of the MechToken Element
4396007Sthurlow //    [in]  nMechListMICLength      -  Length of the MechListMIC Element
4406007Sthurlow //    [out] pnTokenSize             -  Filled out with total size of token
4416007Sthurlow //    [out] pnInternalTokenLength   -  Filled out with length minus length
4426007Sthurlow //                                     for initial token.
4436007Sthurlow //
4446007Sthurlow // Returns:
4456007Sthurlow //    int   Success - SPNEGO_E_SUCCESS
4466007Sthurlow //          Failure - SPNEGO API Error code
4476007Sthurlow //
4486007Sthurlow // Comments :
4496007Sthurlow //    Calculates the required length for a SPNEGO NegTokenTarg token based
4506007Sthurlow //    on the supplied variable length values and which elements are present.
4516007Sthurlow //    Note that because the lengths can be represented by an arbitrary
4526007Sthurlow //    number of bytes in DER encodings, we actually calculate the lengths
4536007Sthurlow //    backwards, so we always know how many bytes we will potentially be
4546007Sthurlow //    writing out.
4556007Sthurlow //
4566007Sthurlow ////////////////////////////////////////////////////////////////////////////
4576007Sthurlow 
CalculateMinSpnegoTargTokenSize(SPNEGO_MECH_OID MechType,SPNEGO_NEGRESULT spnegoNegResult,long nMechTokenLen,long nMechListMICLen,long * pnTokenSize,long * pnInternalTokenLength)4586007Sthurlow int CalculateMinSpnegoTargTokenSize( SPNEGO_MECH_OID MechType,
4596007Sthurlow                                     SPNEGO_NEGRESULT spnegoNegResult, long nMechTokenLen,
4606007Sthurlow                                     long nMechListMICLen, long* pnTokenSize,
4616007Sthurlow                                     long* pnInternalTokenLength )
4626007Sthurlow {
4636007Sthurlow    int   nReturn = SPNEGO_E_INVALID_LENGTH;
4646007Sthurlow 
4656007Sthurlow    // Start at 0.
4666007Sthurlow    long  nTotalLength = 0;
4676007Sthurlow    long  nTempLength= 0L;
4686007Sthurlow 
4696007Sthurlow    // We will calculate this by walking the token backwards
4706007Sthurlow 
4716007Sthurlow    // Start with MIC Element
4726007Sthurlow    if ( nMechListMICLen > 0L )
4736007Sthurlow    {
4746007Sthurlow       nTempLength = ASNDerCalcElementLength( nMechListMICLen, NULL );
4756007Sthurlow 
4766007Sthurlow       // Check for rollover error
4776007Sthurlow       if ( nTempLength < nMechListMICLen )
4786007Sthurlow       {
4796007Sthurlow          goto xEndTokenTargLength;
4806007Sthurlow       }
4816007Sthurlow 
4826007Sthurlow       nTotalLength += nTempLength;
4836007Sthurlow    }
4846007Sthurlow 
4856007Sthurlow    // Next is the MechToken
4866007Sthurlow    if ( nMechTokenLen > 0L )
4876007Sthurlow    {
4886007Sthurlow       nTempLength += ASNDerCalcElementLength( nMechTokenLen, NULL );
4896007Sthurlow 
4906007Sthurlow       // Check for rollover error
4916007Sthurlow       if ( nTempLength < nTotalLength )
4926007Sthurlow       {
4936007Sthurlow          goto xEndTokenTargLength;
4946007Sthurlow       }
4956007Sthurlow 
4966007Sthurlow       nTotalLength = nTempLength;
4976007Sthurlow    }
4986007Sthurlow 
4996007Sthurlow    // Supported MechType
5006007Sthurlow    if ( spnego_mech_oid_NotUsed != MechType )
5016007Sthurlow    {
5026007Sthurlow       // Supported MechOID element - we use the token function since
5036007Sthurlow       // we already know the size of the OID token and value
5046007Sthurlow       nTempLength += ASNDerCalcElementLength( g_stcMechOIDList[MechType].iActualDataLen,
5056007Sthurlow                                              NULL );
5066007Sthurlow 
5076007Sthurlow       // Check for rollover error
5086007Sthurlow       if ( nTempLength < nTotalLength )
5096007Sthurlow       {
5106007Sthurlow          goto xEndTokenTargLength;
5116007Sthurlow       }
5126007Sthurlow 
5136007Sthurlow       nTotalLength = nTempLength;
5146007Sthurlow 
5156007Sthurlow    }  // IF MechType is available
5166007Sthurlow 
5176007Sthurlow    // NegResult Element
5186007Sthurlow    if ( spnego_negresult_NotUsed != spnegoNegResult )
5196007Sthurlow    {
5206007Sthurlow       nTempLength += ASNDerCalcElementLength( SPNEGO_NEGTARG_MAXLEN_NEGRESULT, NULL );
5216007Sthurlow 
5226007Sthurlow       // Check for rollover error
5236007Sthurlow       if ( nTempLength < nTotalLength )
5246007Sthurlow       {
5256007Sthurlow          goto xEndTokenTargLength;
5266007Sthurlow       }
5276007Sthurlow 
5286007Sthurlow       nTotalLength = nTempLength;
5296007Sthurlow 
5306007Sthurlow    }  // IF negResult is available
5316007Sthurlow 
5326007Sthurlow    // Following two fields are the basic header tokens
5336007Sthurlow 
5346007Sthurlow    // Sequence Token
5356007Sthurlow    nTempLength += ASNDerCalcTokenLength( nTotalLength, 0L );
5366007Sthurlow 
5376007Sthurlow    // Check for rollover error
5386007Sthurlow    if ( nTempLength < nTotalLength )
5396007Sthurlow    {
5406007Sthurlow       goto xEndTokenTargLength;
5416007Sthurlow    }
5426007Sthurlow 
5436007Sthurlow    nTotalLength = nTempLength;
5446007Sthurlow 
5456007Sthurlow    // Neg Token Identifier Token
5466007Sthurlow    nTempLength += ASNDerCalcTokenLength( nTotalLength, 0L );
5476007Sthurlow 
5486007Sthurlow    // Check for rollover error
5496007Sthurlow    if ( nTempLength < nTotalLength )
5506007Sthurlow    {
5516007Sthurlow       goto xEndTokenTargLength;
5526007Sthurlow    }
5536007Sthurlow 
5546007Sthurlow    // The internal length doesn't include the number of bytes
5556007Sthurlow    // for the initial token
5566007Sthurlow    *pnInternalTokenLength = nTotalLength;
5576007Sthurlow    nTotalLength = nTempLength;
5586007Sthurlow 
5596007Sthurlow    // We're done
5606007Sthurlow    *pnTokenSize = nTotalLength;
5616007Sthurlow    nReturn = SPNEGO_E_SUCCESS;
5626007Sthurlow 
5636007Sthurlow xEndTokenTargLength:
5646007Sthurlow 
5656007Sthurlow    return nReturn;
5666007Sthurlow 
5676007Sthurlow }
5686007Sthurlow 
5696007Sthurlow /////////////////////////////////////////////////////////////////////////////
5706007Sthurlow //
5716007Sthurlow // Function:
5726007Sthurlow //    CreateSpnegoTargToken
5736007Sthurlow //
5746007Sthurlow // Parameters:
5756007Sthurlow //    [in]  MechType                -  Supported MechType
5766007Sthurlow //    [in]  eNegResult              -  NegResult value
5776007Sthurlow //    [in]  pbMechToken             -  Mech Token Binary Data
5786007Sthurlow //    [in]  ulMechTokenLen          -  Length of Mech Token
5796007Sthurlow //    [in]  pbMechListMIC           -  MechListMIC Binary Data
5806007Sthurlow //    [in]  ulMechListMICn          -  Length of MechListMIC
5816007Sthurlow //    [out] pbTokenData             -  Buffer to write token into.
5826007Sthurlow //    [in]  nTokenLength            -  Length of pbTokenData buffer
5836007Sthurlow //    [in]  nInternalTokenLength    -  Length of full token without leading
5846007Sthurlow //                                     token bytes.
5856007Sthurlow //
5866007Sthurlow // Returns:
5876007Sthurlow //    int   Success - SPNEGO_E_SUCCESS
5886007Sthurlow //          Failure - SPNEGO API Error code
5896007Sthurlow //
5906007Sthurlow // Comments :
5916007Sthurlow //    Uses DER to fill out pbTokenData with a SPNEGO NegTokenTarg Token
5926007Sthurlow //    Note that because the lengths can be represented by an arbitrary
5936007Sthurlow //    number of bytes in DER encodings, we actually calculate the lengths
5946007Sthurlow //    backwards, so we always know how many bytes we will potentially be
5956007Sthurlow //    writing out.
5966007Sthurlow //
5976007Sthurlow ////////////////////////////////////////////////////////////////////////////
5986007Sthurlow 
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)5996007Sthurlow int CreateSpnegoTargToken( SPNEGO_MECH_OID MechType,
6006007Sthurlow           SPNEGO_NEGRESULT eNegResult, unsigned char* pbMechToken,
6016007Sthurlow           unsigned long ulMechTokenLen, unsigned char* pbMechListMIC,
6026007Sthurlow           unsigned long ulMechListMICLen, unsigned char* pbTokenData,
6036007Sthurlow           long nTokenLength, long nInternalTokenLength )
6046007Sthurlow {
6056007Sthurlow    int   nReturn = SPNEGO_E_INVALID_LENGTH;
6066007Sthurlow 
6076007Sthurlow    // Start at 0.
6086007Sthurlow    long  nTempLength= 0L;
6096007Sthurlow    long  nTotalBytesWritten = 0L;
6106007Sthurlow    long  nInternalLength = 0L;
6116007Sthurlow 
6126007Sthurlow    unsigned char  ucTemp = 0;
6136007Sthurlow 
6146007Sthurlow    // We will write the token out backwards to properly handle the cases
6156007Sthurlow    // where the length bytes become adjustable, so the write location
6166007Sthurlow    // is initialized to point *just* past the end of the buffer.
6176007Sthurlow 
6186007Sthurlow    unsigned char* pbWriteTokenData = pbTokenData + nTokenLength;
6196007Sthurlow 
6206007Sthurlow 
6216007Sthurlow    // Start with MIC Element
6226007Sthurlow    if ( ulMechListMICLen > 0L )
6236007Sthurlow    {
6246007Sthurlow       nTempLength = ASNDerCalcElementLength( ulMechListMICLen, &nInternalLength );
6256007Sthurlow 
6266007Sthurlow       // Decrease the pbWriteTokenData, now we know the length and
6276007Sthurlow       // write it out.
6286007Sthurlow 
6296007Sthurlow       pbWriteTokenData -= nTempLength;
6306007Sthurlow       nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGTARG_ELEMENT_MECHLISTMIC,
6316007Sthurlow                               OCTETSTRING, pbMechListMIC, ulMechListMICLen );
6326007Sthurlow 
6336007Sthurlow       // Adjust Values and sanity check
6346007Sthurlow       nTotalBytesWritten += nTempLength;
6356007Sthurlow       nInternalTokenLength -= nTempLength;
6366007Sthurlow 
6376007Sthurlow       if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
6386007Sthurlow       {
6396007Sthurlow          goto xEndWriteNegTokenTarg;
6406007Sthurlow       }
6416007Sthurlow 
6426007Sthurlow    }  // IF MechListMIC is present
6436007Sthurlow 
6446007Sthurlow    // Next is the MechToken
6456007Sthurlow    if ( ulMechTokenLen > 0L )
6466007Sthurlow    {
6476007Sthurlow       nTempLength = ASNDerCalcElementLength( ulMechTokenLen, &nInternalLength );
6486007Sthurlow 
6496007Sthurlow       // Decrease the pbWriteTokenData, now we know the length and
6506007Sthurlow       // write it out.
6516007Sthurlow       pbWriteTokenData -= nTempLength;
6526007Sthurlow       nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGTARG_ELEMENT_RESPONSETOKEN,
6536007Sthurlow                               OCTETSTRING, pbMechToken, ulMechTokenLen );
6546007Sthurlow       // Adjust Values and sanity check
6556007Sthurlow       nTotalBytesWritten += nTempLength;
6566007Sthurlow       nInternalTokenLength -= nTempLength;
6576007Sthurlow 
6586007Sthurlow       if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
6596007Sthurlow       {
6606007Sthurlow          goto xEndWriteNegTokenTarg;
6616007Sthurlow       }
6626007Sthurlow 
6636007Sthurlow    }  // IF MechToken Length is present
6646007Sthurlow 
6656007Sthurlow    // Supported Mech Type
6666007Sthurlow    if ( spnego_mech_oid_NotUsed != MechType )
6676007Sthurlow    {
6686007Sthurlow 
6696007Sthurlow       nTempLength = ASNDerCalcElementLength( g_stcMechOIDList[MechType].iActualDataLen,
6706007Sthurlow                                              &nInternalLength );
6716007Sthurlow 
6726007Sthurlow       // Decrease the pbWriteTokenData, now we know the length and
6736007Sthurlow       // write it out.
6746007Sthurlow       pbWriteTokenData -= nTempLength;
6756007Sthurlow       nTempLength = ASNDerWriteToken( pbWriteTokenData, SPNEGO_NEGTARG_ELEMENT_SUPPORTEDMECH,
6766007Sthurlow                                        g_stcMechOIDList[MechType].ucOid,
6776007Sthurlow                                        g_stcMechOIDList[MechType].iLen );
6786007Sthurlow 
6796007Sthurlow       // Adjust Values and sanity check
6806007Sthurlow       nTotalBytesWritten += nTempLength;
6816007Sthurlow       nInternalTokenLength -= nTempLength;
6826007Sthurlow 
6836007Sthurlow       if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
6846007Sthurlow       {
6856007Sthurlow          goto xEndWriteNegTokenTarg;
6866007Sthurlow       }
6876007Sthurlow 
6886007Sthurlow    }  // IF MechType is present
6896007Sthurlow 
6906007Sthurlow    // Neg Result
6916007Sthurlow    // NegResult Element
6926007Sthurlow    if ( spnego_negresult_NotUsed != eNegResult )
6936007Sthurlow    {
6946007Sthurlow       ucTemp = (unsigned char) eNegResult;
6956007Sthurlow 
6966007Sthurlow       nTempLength = ASNDerCalcElementLength( SPNEGO_NEGTARG_MAXLEN_NEGRESULT, &nInternalLength );
6976007Sthurlow 
6986007Sthurlow       // Decrease the pbWriteTokenData, now we know the length and
6996007Sthurlow       // write it out.
7006007Sthurlow       pbWriteTokenData -= nTempLength;
7016007Sthurlow       nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGTARG_ELEMENT_NEGRESULT,
7026007Sthurlow                               ENUMERATED, &ucTemp, SPNEGO_NEGTARG_MAXLEN_NEGRESULT );
7036007Sthurlow 
7046007Sthurlow       // Adjust Values and sanity check
7056007Sthurlow       nTotalBytesWritten += nTempLength;
7066007Sthurlow       nInternalTokenLength -= nTempLength;
7076007Sthurlow 
7086007Sthurlow       if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
7096007Sthurlow       {
7106007Sthurlow          goto xEndWriteNegTokenTarg;
7116007Sthurlow       }
7126007Sthurlow 
7136007Sthurlow    }  // If eNegResult is available
7146007Sthurlow 
7156007Sthurlow    // The next tokens we're writing out reflect the total number of bytes
7166007Sthurlow    // we have actually written out.
7176007Sthurlow 
7186007Sthurlow    // Sequence Token
7196007Sthurlow    nTempLength = ASNDerCalcTokenLength( nTotalBytesWritten, 0L );
7206007Sthurlow 
7216007Sthurlow    // Decrease the pbWriteTokenData, now we know the length and
7226007Sthurlow    // write it out.
7236007Sthurlow    pbWriteTokenData -= nTempLength;
7246007Sthurlow    nTempLength = ASNDerWriteToken( pbWriteTokenData, SPNEGO_CONSTRUCTED_SEQUENCE,
7256007Sthurlow                                     NULL, nTotalBytesWritten );
7266007Sthurlow 
7276007Sthurlow    // Adjust Values and sanity check
7286007Sthurlow    nTotalBytesWritten += nTempLength;
7296007Sthurlow    nInternalTokenLength -= nTempLength;
7306007Sthurlow 
7316007Sthurlow    if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 )
7326007Sthurlow    {
7336007Sthurlow       goto xEndWriteNegTokenTarg;
7346007Sthurlow    }
7356007Sthurlow 
7366007Sthurlow    // Neg Targ Token Identifier Token
7376007Sthurlow    nTempLength = ASNDerCalcTokenLength( nTotalBytesWritten, 0L );
7386007Sthurlow 
7396007Sthurlow    // Decrease the pbWriteTokenData, now we know the length and
7406007Sthurlow    // write it out.
7416007Sthurlow    pbWriteTokenData -= nTempLength;
7426007Sthurlow    nTempLength = ASNDerWriteToken( pbWriteTokenData, SPNEGO_NEGTARG_TOKEN_IDENTIFIER,
7436007Sthurlow                                     NULL, nTotalBytesWritten );
7446007Sthurlow 
7456007Sthurlow    // Adjust Values and sanity check
7466007Sthurlow    nTotalBytesWritten += nTempLength;
7476007Sthurlow 
7486007Sthurlow    // Don't adjust the internal token length here, it doesn't account
7496007Sthurlow    // the initial bytes written out (we really don't need to keep
7506007Sthurlow    // a running count here, but for debugging, it helps to be able
7516007Sthurlow    // to see the total number of bytes written out as well as the
7526007Sthurlow    // number of bytes left to write).
7536007Sthurlow 
7546007Sthurlow    if ( nTotalBytesWritten == nTokenLength && nInternalTokenLength == 0 &&
7556007Sthurlow          pbWriteTokenData == pbTokenData )
7566007Sthurlow    {
7576007Sthurlow       nReturn = SPNEGO_E_SUCCESS;
7586007Sthurlow    }
7596007Sthurlow 
7606007Sthurlow 
7616007Sthurlow xEndWriteNegTokenTarg:
7626007Sthurlow 
7636007Sthurlow    return nReturn;
7646007Sthurlow 
7656007Sthurlow 
7666007Sthurlow }
7676007Sthurlow 
7686007Sthurlow 
7696007Sthurlow /////////////////////////////////////////////////////////////////////////////
7706007Sthurlow //
7716007Sthurlow // Function:
7726007Sthurlow //    AllocEmptySpnegoToken
7736007Sthurlow //
7746007Sthurlow // Parameters:
7756007Sthurlow //    [in]  ucCopyData        -  Flag to copy data or pointer.
7766007Sthurlow //    [in]  ulFlags           -  Flags for SPNEGO_TOKEN data member.
7776007Sthurlow //    [in]  pbTokenData       -  Binary token data.
7786007Sthurlow //    [in]  ulTokenSize       -  Size of pbTokenData.
7796007Sthurlow //
7806007Sthurlow // Returns:
7816007Sthurlow //    SPNEGO_TOKEN*  Success - Pointer to initialized SPNEGO_TOKEN struct
7826007Sthurlow //                   Failure - NULL
7836007Sthurlow //
7846007Sthurlow // Comments :
7856007Sthurlow //    Allocates a SPNEGO_TOKEN data structure and initializes it.  Based on
7866007Sthurlow //    the value of ucCopyData, if non-zero, we copy the data into a buffer
7876007Sthurlow //    we allocate in this function, otherwise, we copy the data pointer
7886007Sthurlow //    direcly.
7896007Sthurlow //
7906007Sthurlow ////////////////////////////////////////////////////////////////////////////
7916007Sthurlow 
AllocEmptySpnegoToken(unsigned char ucCopyData,unsigned long ulFlags,unsigned char * pbTokenData,unsigned long ulTokenSize)7926007Sthurlow SPNEGO_TOKEN* AllocEmptySpnegoToken( unsigned char ucCopyData, unsigned long ulFlags,
7936007Sthurlow                                     unsigned char * pbTokenData, unsigned long ulTokenSize )
7946007Sthurlow {
7956007Sthurlow    SPNEGO_TOKEN*  pSpnegoToken = (SPNEGO_TOKEN*) calloc( 1, sizeof(SPNEGO_TOKEN) );
7966007Sthurlow 
7976007Sthurlow    if ( NULL != pSpnegoToken )
7986007Sthurlow    {
7996007Sthurlow       // Set the token size
8006007Sthurlow       pSpnegoToken->nStructSize = SPNEGO_TOKEN_SIZE;
8016007Sthurlow 
8026007Sthurlow       // Initialize the element array
8036007Sthurlow       InitSpnegoTokenElementArray( pSpnegoToken );
8046007Sthurlow 
8056007Sthurlow       // Assign the flags value
8066007Sthurlow       pSpnegoToken->ulFlags = ulFlags;
8076007Sthurlow 
8086007Sthurlow       //
8096007Sthurlow       // IF ucCopyData is TRUE, we will allocate a buffer and copy data into it.
8106007Sthurlow       // Otherwise, we will just copy the pointer and the length.  This is so we
8116007Sthurlow       // can cut out additional allocations for performance reasons
8126007Sthurlow       //
8136007Sthurlow 
8146007Sthurlow       if ( SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA == ucCopyData )
8156007Sthurlow       {
8166007Sthurlow          // Alloc the internal buffer.  Cleanup on failure.
8176007Sthurlow          pSpnegoToken->pbBinaryData = (unsigned char*) calloc( ulTokenSize, sizeof(unsigned char) );
8186007Sthurlow 
8196007Sthurlow          if ( NULL != pSpnegoToken->pbBinaryData )
8206007Sthurlow          {
8216007Sthurlow             // We must ALWAYS free this buffer
8226007Sthurlow             pSpnegoToken->ulFlags |= SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA;
8236007Sthurlow 
8246007Sthurlow             // Copy the data locally
8256007Sthurlow             memcpy( pSpnegoToken->pbBinaryData, pbTokenData, ulTokenSize );
8266007Sthurlow             pSpnegoToken->ulBinaryDataLen = ulTokenSize;
8276007Sthurlow          }
8286007Sthurlow          else
8296007Sthurlow          {
8306007Sthurlow             free( pSpnegoToken );
8316007Sthurlow             pSpnegoToken = NULL;
8326007Sthurlow          }
8336007Sthurlow 
8346007Sthurlow       }  // IF ucCopyData
8356007Sthurlow       else
8366007Sthurlow       {
8376007Sthurlow          // Copy the pointer and the length directly - ulFlags will control whether or not
8386007Sthurlow          // we are allowed to free the value
8396007Sthurlow 
8406007Sthurlow          pSpnegoToken->pbBinaryData = pbTokenData;
8416007Sthurlow          pSpnegoToken->ulBinaryDataLen = ulTokenSize;
8426007Sthurlow       }
8436007Sthurlow 
8446007Sthurlow    }
8456007Sthurlow 
8466007Sthurlow    return pSpnegoToken;
8476007Sthurlow }
8486007Sthurlow 
8496007Sthurlow /////////////////////////////////////////////////////////////////////////////
8506007Sthurlow //
8516007Sthurlow // Function:
8526007Sthurlow //    FreeSpnegoToken
8536007Sthurlow //
8546007Sthurlow // Parameters:
8556007Sthurlow //    [in]  pSpnegoToken      -  Points to SPNEGO_TOKEN to free.
8566007Sthurlow //
8576007Sthurlow // Returns:
8586007Sthurlow //    void
8596007Sthurlow //
8606007Sthurlow // Comments :
8616007Sthurlow //    If non-NULL, interprets pSpnegoToken, freeing any internal allocations
8626007Sthurlow //    and finally the actual structure.
8636007Sthurlow //
8646007Sthurlow ////////////////////////////////////////////////////////////////////////////
8656007Sthurlow 
FreeSpnegoToken(SPNEGO_TOKEN * pSpnegoToken)8666007Sthurlow void FreeSpnegoToken( SPNEGO_TOKEN* pSpnegoToken )
8676007Sthurlow {
8686007Sthurlow    if ( NULL != pSpnegoToken )
8696007Sthurlow    {
8706007Sthurlow 
8716007Sthurlow       // Cleanup internal allocation per the flags
8726007Sthurlow       if ( pSpnegoToken->ulFlags & SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA &&
8736007Sthurlow          NULL != pSpnegoToken->pbBinaryData )
8746007Sthurlow       {
8756007Sthurlow          free( pSpnegoToken->pbBinaryData );
8766007Sthurlow          pSpnegoToken->pbBinaryData = NULL;
8776007Sthurlow       }
8786007Sthurlow 
8796007Sthurlow       free ( pSpnegoToken );
8806007Sthurlow    }
8816007Sthurlow }
8826007Sthurlow 
8836007Sthurlow /////////////////////////////////////////////////////////////////////////////
8846007Sthurlow //
8856007Sthurlow // Function:
8866007Sthurlow //    InitSpnegoTokenElementArray
8876007Sthurlow //
8886007Sthurlow // Parameters:
8896007Sthurlow //    [in]  pSpnegoToken      -  Points to SPNEGO_TOKEN structure.
8906007Sthurlow //
8916007Sthurlow // Returns:
8926007Sthurlow //    void
8936007Sthurlow //
8946007Sthurlow // Comments :
8956007Sthurlow //    Initializes the element array data member of a SPNEGO_TOKEN data
8966007Sthurlow //    structure.
8976007Sthurlow //
8986007Sthurlow ////////////////////////////////////////////////////////////////////////////
8996007Sthurlow 
InitSpnegoTokenElementArray(SPNEGO_TOKEN * pSpnegoToken)9006007Sthurlow void InitSpnegoTokenElementArray( SPNEGO_TOKEN* pSpnegoToken )
9016007Sthurlow {
9026007Sthurlow    int   nCtr;
9036007Sthurlow 
9046007Sthurlow    // Set the number of elemnts
9056007Sthurlow    pSpnegoToken->nNumElements = MAX_NUM_TOKEN_ELEMENTS;
9066007Sthurlow 
9076007Sthurlow    //
9086007Sthurlow    // Initially, all elements are unavailable
9096007Sthurlow    //
9106007Sthurlow 
9116007Sthurlow    for ( nCtr = 0; nCtr < MAX_NUM_TOKEN_ELEMENTS; nCtr++ )
9126007Sthurlow    {
9136007Sthurlow       // Set the element size as well
9146007Sthurlow       pSpnegoToken->aElementArray[ nCtr ].nStructSize = SPNEGO_ELEMENT_SIZE;
9156007Sthurlow       pSpnegoToken->aElementArray[ nCtr ].iElementPresent = SPNEGO_TOKEN_ELEMENT_UNAVAILABLE;
9166007Sthurlow    }
9176007Sthurlow 
9186007Sthurlow }
9196007Sthurlow 
9206007Sthurlow /////////////////////////////////////////////////////////////////////////////
9216007Sthurlow //
9226007Sthurlow // Function:
9236007Sthurlow //    InitSpnegoTokenType
9246007Sthurlow //
9256007Sthurlow // Parameters:
9266007Sthurlow //    [in]  pSpnegoToken            -  Points to SPNEGO_TOKEN structure.
9276007Sthurlow //    [out] pnTokenLength           -  Filled out with total token length
9286007Sthurlow //    [out] pnRemainingTokenLength  -  Filled out with remaining length
9296007Sthurlow //                                     after header is parsed
9306007Sthurlow //    [out] ppbFirstElement         -  Filled out with pointer to first
9316007Sthurlow //                                     element after header info.
9326007Sthurlow //
9336007Sthurlow // Returns:
9346007Sthurlow //    int   Success - SPNEGO_E_SUCCESS
9356007Sthurlow //          Failure - SPNEGO API Error code
9366007Sthurlow //
9376007Sthurlow // Comments :
9386007Sthurlow //    Walks the underlying binary data for a SPNEGO_TOKEN data structure
9396007Sthurlow //    and determines the type of the underlying token based on token header
9406007Sthurlow //    information.
9416007Sthurlow //
9426007Sthurlow ////////////////////////////////////////////////////////////////////////////
9436007Sthurlow 
InitSpnegoTokenType(SPNEGO_TOKEN * pSpnegoToken,long * pnTokenLength,long * pnRemainingTokenLength,unsigned char ** ppbFirstElement)9446007Sthurlow int InitSpnegoTokenType( SPNEGO_TOKEN* pSpnegoToken, long* pnTokenLength,
9456007Sthurlow                            long* pnRemainingTokenLength, unsigned char** ppbFirstElement )
9466007Sthurlow {
9476007Sthurlow    int   nReturn = SPNEGO_E_INVALID_TOKEN;
9486007Sthurlow    long  nActualTokenLength = 0L;
9496007Sthurlow    long  nBoundaryLength = pSpnegoToken->ulBinaryDataLen;
9506007Sthurlow    unsigned char* pbTokenData = pSpnegoToken->pbBinaryData;
9516007Sthurlow 
9526007Sthurlow    //
9536007Sthurlow    // First byte MUST be either an APP_CONSTRUCT or the NEGTARG_TOKEN_TARG
9546007Sthurlow    //
9556007Sthurlow 
9566007Sthurlow    if ( SPNEGO_NEGINIT_APP_CONSTRUCT == *pbTokenData )
9576007Sthurlow    {
9586007Sthurlow       // Validate the above token - this will tell us the actual length of the token
9596007Sthurlow       // per the encoding (minus the actual token bytes)
9606007Sthurlow       if ( ( nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_NEGINIT_APP_CONSTRUCT, 0L, nBoundaryLength,
9616007Sthurlow                                           pnTokenLength, &nActualTokenLength ) )
9626007Sthurlow                        == SPNEGO_E_SUCCESS )
9636007Sthurlow       {
9646007Sthurlow          // Initialize the remaining token length value.  This will be used
9656007Sthurlow          // to tell the caller how much token there is left once we've parsed
9666007Sthurlow          // the header (they could calculate it from the other values, but this
9676007Sthurlow          // is a bit friendlier)
9686007Sthurlow          *pnRemainingTokenLength = *pnTokenLength;
9696007Sthurlow 
9706007Sthurlow          // Make adjustments to next token
9716007Sthurlow          pbTokenData += nActualTokenLength;
9726007Sthurlow          nBoundaryLength -= nActualTokenLength;
9736007Sthurlow 
9746007Sthurlow          // The next token should be an OID
9756007Sthurlow          if ( ( nReturn = ASNDerCheckOID( pbTokenData, spnego_mech_oid_Spnego, nBoundaryLength,
9766007Sthurlow                                           &nActualTokenLength ) ) == SPNEGO_E_SUCCESS )
9776007Sthurlow          {
9786007Sthurlow             // Make adjustments to next token
9796007Sthurlow             pbTokenData += nActualTokenLength;
9806007Sthurlow             nBoundaryLength -= nActualTokenLength;
9816007Sthurlow             *pnRemainingTokenLength -= nActualTokenLength;
9826007Sthurlow 
9836007Sthurlow             // The next token should specify the NegTokenInit
9846007Sthurlow             if ( ( nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_NEGINIT_TOKEN_IDENTIFIER,
9856007Sthurlow                                                 *pnRemainingTokenLength, nBoundaryLength, pnTokenLength,
9866007Sthurlow                                                 &nActualTokenLength ) )
9876007Sthurlow                              == SPNEGO_E_SUCCESS )
9886007Sthurlow             {
9896007Sthurlow                // Make adjustments to next token
9906007Sthurlow                pbTokenData += nActualTokenLength;
9916007Sthurlow                nBoundaryLength -= nActualTokenLength;
9926007Sthurlow                *pnRemainingTokenLength -= nActualTokenLength;
9936007Sthurlow 
9946007Sthurlow                // The next token should specify the start of a sequence
9956007Sthurlow                if ( ( nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_CONSTRUCTED_SEQUENCE,
9966007Sthurlow                                                    *pnRemainingTokenLength, nBoundaryLength, pnTokenLength,
9976007Sthurlow                                                    &nActualTokenLength ) )
9986007Sthurlow                                 == SPNEGO_E_SUCCESS )
9996007Sthurlow                {
10006007Sthurlow                   // NegTokenInit header is now checked out!
10016007Sthurlow 
10026007Sthurlow                   // Make adjustments to next token
10036007Sthurlow                   *pnRemainingTokenLength -= nActualTokenLength;
10046007Sthurlow 
10056007Sthurlow                   // Store pointer to first element
10066007Sthurlow                   *ppbFirstElement = pbTokenData + nActualTokenLength;
10076007Sthurlow                   pSpnegoToken->ucTokenType = SPNEGO_TOKEN_INIT;
10086007Sthurlow                }  // IF Check Sequence Token
10096007Sthurlow 
10106007Sthurlow             }  // IF Check NegTokenInit token
10116007Sthurlow 
10126007Sthurlow 
10136007Sthurlow          }  // IF Check for SPNEGO OID
10146007Sthurlow 
10156007Sthurlow 
10166007Sthurlow       }  // IF check app construct token
10176007Sthurlow 
10186007Sthurlow    }
10196007Sthurlow    else if ( SPNEGO_NEGTARG_TOKEN_IDENTIFIER == *pbTokenData )
10206007Sthurlow    {
10216007Sthurlow 
10226007Sthurlow       // The next token should specify the NegTokenInit
10236007Sthurlow       if ( ( nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_NEGTARG_TOKEN_IDENTIFIER,
10246007Sthurlow                                           *pnRemainingTokenLength, nBoundaryLength, pnTokenLength,
10256007Sthurlow                                           &nActualTokenLength ) )
10266007Sthurlow                        == SPNEGO_E_SUCCESS )
10276007Sthurlow       {
10286007Sthurlow          // Initialize the remaining token length value.  This will be used
10296007Sthurlow          // to tell the caller how much token there is left once we've parsed
10306007Sthurlow          // the header (they could calculate it from the other values, but this
10316007Sthurlow          // is a bit friendlier)
10326007Sthurlow          *pnRemainingTokenLength = *pnTokenLength;
10336007Sthurlow 
10346007Sthurlow          // Make adjustments to next token
10356007Sthurlow          pbTokenData += nActualTokenLength;
10366007Sthurlow          nBoundaryLength -= nActualTokenLength;
10376007Sthurlow 
10386007Sthurlow          // The next token should specify the start of a sequence
10396007Sthurlow          if ( ( nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_CONSTRUCTED_SEQUENCE,
10406007Sthurlow                                              *pnRemainingTokenLength, nBoundaryLength, pnTokenLength,
10416007Sthurlow                                              &nActualTokenLength ) )
10426007Sthurlow                           == SPNEGO_E_SUCCESS )
10436007Sthurlow          {
10446007Sthurlow             // NegTokenInit header is now checked out!
10456007Sthurlow 
10466007Sthurlow             // Make adjustments to next token
10476007Sthurlow             *pnRemainingTokenLength -= nActualTokenLength;
10486007Sthurlow 
10496007Sthurlow             // Store pointer to first element
10506007Sthurlow             *ppbFirstElement = pbTokenData + nActualTokenLength;
10516007Sthurlow             pSpnegoToken->ucTokenType = SPNEGO_TOKEN_TARG;
10526007Sthurlow          }  // IF Check Sequence Token
10536007Sthurlow 
10546007Sthurlow       }  // IF Check NegTokenInit token
10556007Sthurlow 
10566007Sthurlow    }  // ELSE IF it's a NegTokenTarg
10576007Sthurlow 
10586007Sthurlow    return nReturn;
10596007Sthurlow }
10606007Sthurlow 
10616007Sthurlow 
10626007Sthurlow /////////////////////////////////////////////////////////////////////////////
10636007Sthurlow //
10646007Sthurlow // Function:
10656007Sthurlow //    GetSpnegoInitTokenMechList
10666007Sthurlow //
10676007Sthurlow // Parameters:
10686007Sthurlow //    [in]  pbTokenData             -  Points to binary MechList element
10696007Sthurlow //                                     in NegTokenInit.
10706007Sthurlow //    [in]  nMechListLength         -  Length of the MechList
10716007Sthurlow //    [out] pSpnegoElement          -  Filled out with MechList Element
10726007Sthurlow //                                     data.
10736007Sthurlow //
10746007Sthurlow // Returns:
10756007Sthurlow //    int   Success - SPNEGO_E_SUCCESS
10766007Sthurlow //          Failure - SPNEGO API Error code
10776007Sthurlow //
10786007Sthurlow // Comments :
10796007Sthurlow //    Checks that pbTokenData is pointing at something that at least
10806007Sthurlow //    *looks* like a MechList and then fills out the supplied
10816007Sthurlow //    SPNEGO_ELEMENT structure.
10826007Sthurlow //
10836007Sthurlow ////////////////////////////////////////////////////////////////////////////
10846007Sthurlow 
GetSpnegoInitTokenMechList(unsigned char * pbTokenData,int nMechListLength,SPNEGO_ELEMENT * pSpnegoElement)10856007Sthurlow int GetSpnegoInitTokenMechList( unsigned char* pbTokenData, int nMechListLength,
10866007Sthurlow                                  SPNEGO_ELEMENT* pSpnegoElement )
10876007Sthurlow {
10886007Sthurlow    int   nReturn = SPNEGO_E_INVALID_TOKEN;
10896007Sthurlow    long  nLength = 0L;
10906007Sthurlow    long  nActualTokenLength = 0L;
10916007Sthurlow 
10926007Sthurlow    // Actual MechList is prepended by a Constructed Sequence Token
10936007Sthurlow    if ( ( nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_CONSTRUCTED_SEQUENCE,
10946007Sthurlow                                        nMechListLength, nMechListLength,
10956007Sthurlow                                        &nLength, &nActualTokenLength ) )
10966007Sthurlow                              == SPNEGO_E_SUCCESS )
10976007Sthurlow    {
10986007Sthurlow       // Adjust for this token
10996007Sthurlow       nMechListLength -= nActualTokenLength;
11006007Sthurlow       pbTokenData += nActualTokenLength;
11016007Sthurlow 
11026007Sthurlow       // Perform simple validation of the actual MechList (i.e. ensure that
11036007Sthurlow       // the OIDs in the MechList are reasonable).
11046007Sthurlow 
11056007Sthurlow       if ( ( nReturn = ValidateMechList( pbTokenData, nLength ) ) == SPNEGO_E_SUCCESS )
11066007Sthurlow       {
11076007Sthurlow          // Initialize the element now
11086007Sthurlow          pSpnegoElement->eElementType = spnego_init_mechtypes;
11096007Sthurlow          pSpnegoElement->iElementPresent = SPNEGO_TOKEN_ELEMENT_AVAILABLE;
11106007Sthurlow          pSpnegoElement->type = SPNEGO_MECHLIST_TYPE;
11116007Sthurlow          pSpnegoElement->nDatalength = nLength;
11126007Sthurlow          pSpnegoElement->pbData = pbTokenData;
11136007Sthurlow       }
11146007Sthurlow 
11156007Sthurlow    }  // IF Check Token
11166007Sthurlow 
11176007Sthurlow    return nReturn;
11186007Sthurlow }
11196007Sthurlow 
11206007Sthurlow /////////////////////////////////////////////////////////////////////////////
11216007Sthurlow //
11226007Sthurlow // Function:
11236007Sthurlow //    InitSpnegoTokenElementFromBasicType
11246007Sthurlow //
11256007Sthurlow // Parameters:
11266007Sthurlow //    [in]  pbTokenData             -  Points to binary element data in
11276007Sthurlow //                                     a SPNEGO token.
11286007Sthurlow //    [in]  nElementLength          -  Length of the element
11296007Sthurlow //    [in]  ucExpectedType          -  Expected DER type.
11306007Sthurlow //    [in]  spnegoElementType       -  Which element is this?
11316007Sthurlow //    [out] pSpnegoElement          -  Filled out with element data.
11326007Sthurlow //
11336007Sthurlow // Returns:
11346007Sthurlow //    int   Success - SPNEGO_E_SUCCESS
11356007Sthurlow //          Failure - SPNEGO API Error code
11366007Sthurlow //
11376007Sthurlow // Comments :
11386007Sthurlow //    Checks that pbTokenData is pointing at the specified DER type.  If so,
11396007Sthurlow //    then we verify that lengths are proper and then fill out the
11406007Sthurlow //    SPNEGO_ELEMENT data structure.
11416007Sthurlow //
11426007Sthurlow ////////////////////////////////////////////////////////////////////////////
11436007Sthurlow 
InitSpnegoTokenElementFromBasicType(unsigned char * pbTokenData,int nElementLength,unsigned char ucExpectedType,SPNEGO_ELEMENT_TYPE spnegoElementType,SPNEGO_ELEMENT * pSpnegoElement)11446007Sthurlow int InitSpnegoTokenElementFromBasicType( unsigned char* pbTokenData, int nElementLength,
11456007Sthurlow                                           unsigned char ucExpectedType,
11466007Sthurlow                                           SPNEGO_ELEMENT_TYPE spnegoElementType,
11476007Sthurlow                                           SPNEGO_ELEMENT* pSpnegoElement )
11486007Sthurlow {
11496007Sthurlow    int   nReturn = SPNEGO_E_UNEXPECTED_TYPE;
11506007Sthurlow    long  nLength = 0L;
11516007Sthurlow    long  nActualTokenLength = 0L;
11526007Sthurlow 
11536007Sthurlow    // The type BYTE must match our token data or something is badly wrong
11546007Sthurlow    if ( *pbTokenData == ucExpectedType )
11556007Sthurlow    {
11566007Sthurlow 
11576007Sthurlow       // Check that we are pointing at the specified type
11586007Sthurlow       if ( ( nReturn = ASNDerCheckToken( pbTokenData, ucExpectedType,
11596007Sthurlow                                           nElementLength, nElementLength,
11606007Sthurlow                                           &nLength, &nActualTokenLength ) )
11616007Sthurlow                                 == SPNEGO_E_SUCCESS )
11626007Sthurlow       {
11636007Sthurlow          // Adjust for this token
11646007Sthurlow          nElementLength -= nActualTokenLength;
11656007Sthurlow          pbTokenData += nActualTokenLength;
11666007Sthurlow 
11676007Sthurlow          // Initialize the element now
11686007Sthurlow          pSpnegoElement->eElementType = spnegoElementType;
11696007Sthurlow          pSpnegoElement->iElementPresent = SPNEGO_TOKEN_ELEMENT_AVAILABLE;
11706007Sthurlow          pSpnegoElement->type = ucExpectedType;
11716007Sthurlow          pSpnegoElement->nDatalength = nLength;
11726007Sthurlow          pSpnegoElement->pbData = pbTokenData;
11736007Sthurlow       }
11746007Sthurlow 
11756007Sthurlow    }  // IF type makes sense
11766007Sthurlow 
11776007Sthurlow    return nReturn;
11786007Sthurlow }
11796007Sthurlow 
11806007Sthurlow 
11816007Sthurlow /////////////////////////////////////////////////////////////////////////////
11826007Sthurlow //
11836007Sthurlow // Function:
11846007Sthurlow //    InitSpnegoTokenElementFromOID
11856007Sthurlow //
11866007Sthurlow // Parameters:
11876007Sthurlow //    [in]  pbTokenData             -  Points to binary element data in
11886007Sthurlow //                                     a SPNEGO token.
11896007Sthurlow //    [in]  nElementLength          -  Length of the element
11906007Sthurlow //    [in]  spnegoElementType       -  Which element is this?
11916007Sthurlow //    [out] pSpnegoElement          -  Filled out with element data.
11926007Sthurlow //
11936007Sthurlow // Returns:
11946007Sthurlow //    int   Success - SPNEGO_E_SUCCESS
11956007Sthurlow //          Failure - SPNEGO API Error code
11966007Sthurlow //
11976007Sthurlow // Comments :
11986007Sthurlow //    Initializes a SpnegoElement from an OID - normally, this would have
11996007Sthurlow //    used the Basic Type function above, but since we do binary compares
12006007Sthurlow //    on the OIDs against the DER information as well as the OID, we need
12016007Sthurlow //    to account for that.
12026007Sthurlow //
12036007Sthurlow ////////////////////////////////////////////////////////////////////////////
12046007Sthurlow 
InitSpnegoTokenElementFromOID(unsigned char * pbTokenData,int nElementLength,SPNEGO_ELEMENT_TYPE spnegoElementType,SPNEGO_ELEMENT * pSpnegoElement)12056007Sthurlow int InitSpnegoTokenElementFromOID( unsigned char* pbTokenData, int nElementLength,
12066007Sthurlow                                    SPNEGO_ELEMENT_TYPE spnegoElementType,
12076007Sthurlow                                    SPNEGO_ELEMENT* pSpnegoElement )
12086007Sthurlow {
12096007Sthurlow    int   nReturn = SPNEGO_E_UNEXPECTED_TYPE;
12106007Sthurlow    long  nLength = 0L;
12116007Sthurlow    long  nActualTokenLength = 0L;
12126007Sthurlow 
12136007Sthurlow    // The type BYTE must match our token data or something is badly wrong
12146007Sthurlow    if ( *pbTokenData == OID )
12156007Sthurlow    {
12166007Sthurlow 
12176007Sthurlow       // Check that we are pointing at an OID type
12186007Sthurlow       if ( ( nReturn = ASNDerCheckToken( pbTokenData, OID,
12196007Sthurlow                                           nElementLength, nElementLength,
12206007Sthurlow                                           &nLength, &nActualTokenLength ) )
12216007Sthurlow                                 == SPNEGO_E_SUCCESS )
12226007Sthurlow       {
12236007Sthurlow          // Don't adjust any values for this function
12246007Sthurlow 
12256007Sthurlow          // Initialize the element now
12266007Sthurlow          pSpnegoElement->eElementType = spnegoElementType;
12276007Sthurlow          pSpnegoElement->iElementPresent = SPNEGO_TOKEN_ELEMENT_AVAILABLE;
12286007Sthurlow          pSpnegoElement->type = OID;
12296007Sthurlow          pSpnegoElement->nDatalength = nElementLength;
12306007Sthurlow          pSpnegoElement->pbData = pbTokenData;
12316007Sthurlow       }
12326007Sthurlow 
12336007Sthurlow    }  // IF type makes sense
12346007Sthurlow 
12356007Sthurlow    return nReturn;
12366007Sthurlow }
12376007Sthurlow 
12386007Sthurlow 
12396007Sthurlow /////////////////////////////////////////////////////////////////////////////
12406007Sthurlow //
12416007Sthurlow // Function:
12426007Sthurlow //    InitSpnegoTokenElements
12436007Sthurlow //
12446007Sthurlow // Parameters:
12456007Sthurlow //    [in]  pSpnegoToken            -  Points to SPNEGO_TOKEN struct
12466007Sthurlow //    [in]  pbTokenData             -  Points to initial binary element
12476007Sthurlow //                                     data in a SPNEGO token.
12486007Sthurlow //    [in]  nRemainingTokenLength   -  Length remaining past header
12496007Sthurlow //
12506007Sthurlow // Returns:
12516007Sthurlow //    int   Success - SPNEGO_E_SUCCESS
12526007Sthurlow //          Failure - SPNEGO API Error code
12536007Sthurlow //
12546007Sthurlow // Comments :
12556007Sthurlow //    Interprets the data at pbTokenData based on the TokenType in
12566007Sthurlow //    pSpnegoToken.  Since some elements are optional (technically all are
12576007Sthurlow //    but the token becomes quite useless if this is so), we check if
12586007Sthurlow //    an element exists before filling out the element in the array.
12596007Sthurlow //
12606007Sthurlow ////////////////////////////////////////////////////////////////////////////
12616007Sthurlow 
InitSpnegoTokenElements(SPNEGO_TOKEN * pSpnegoToken,unsigned char * pbTokenData,long nRemainingTokenLength)12626007Sthurlow int InitSpnegoTokenElements( SPNEGO_TOKEN* pSpnegoToken, unsigned char* pbTokenData,
12636007Sthurlow                            long nRemainingTokenLength  )
12646007Sthurlow {
12656007Sthurlow    //
12666007Sthurlow    // The following arrays contain the token identifiers for the elements
12676007Sthurlow    // comprising the actual token.  All values are optional, and there are
12686007Sthurlow    // no defaults.
12696007Sthurlow    //
12706007Sthurlow 
12716007Sthurlow    static unsigned char abNegTokenInitElements[] =
12726007Sthurlow       { SPNEGO_NEGINIT_ELEMENT_MECHTYPES, SPNEGO_NEGINIT_ELEMENT_REQFLAGS,
12736007Sthurlow          SPNEGO_NEGINIT_ELEMENT_MECHTOKEN, SPNEGO_NEGINIT_ELEMENT_MECHLISTMIC };
12746007Sthurlow 
12756007Sthurlow    static unsigned char abNegTokenTargElements[] =
12766007Sthurlow       { SPNEGO_NEGTARG_ELEMENT_NEGRESULT, SPNEGO_NEGTARG_ELEMENT_SUPPORTEDMECH,
12776007Sthurlow          SPNEGO_NEGTARG_ELEMENT_RESPONSETOKEN, SPNEGO_NEGTARG_ELEMENT_MECHLISTMIC };
12786007Sthurlow 
12796007Sthurlow    int   nReturn = SPNEGO_E_SUCCESS;
12806007Sthurlow    int   nCtr = 0L;
12816007Sthurlow    long  nElementLength = 0L;
12826007Sthurlow    long  nActualTokenLength = 0L;
12836007Sthurlow    unsigned char* pbElements = NULL;
12846007Sthurlow 	unsigned char * ptok;
12856007Sthurlow 	long  tlen, elen, len;
12866007Sthurlow 
12876007Sthurlow    // Point to the correct array
12886007Sthurlow    switch( pSpnegoToken->ucTokenType )
12896007Sthurlow    {
12906007Sthurlow       case SPNEGO_TOKEN_INIT:
12916007Sthurlow       {
12926007Sthurlow          pbElements = abNegTokenInitElements;
12936007Sthurlow       }
12946007Sthurlow       break;
12956007Sthurlow 
12966007Sthurlow       case SPNEGO_TOKEN_TARG:
12976007Sthurlow       {
12986007Sthurlow          pbElements = abNegTokenTargElements;
12996007Sthurlow       }
13006007Sthurlow       break;
13016007Sthurlow 
13026007Sthurlow    }  // SWITCH tokentype
13036007Sthurlow 
13046007Sthurlow    //
13056007Sthurlow    // Enumerate the element arrays and look for the tokens at our current location
13066007Sthurlow    //
13076007Sthurlow 
13086007Sthurlow    for ( nCtr = 0L;
13096007Sthurlow          SPNEGO_E_SUCCESS == nReturn &&
13106007Sthurlow          nCtr < MAX_NUM_TOKEN_ELEMENTS &&
13116007Sthurlow          nRemainingTokenLength > 0L;
13126007Sthurlow          nCtr++ )
13136007Sthurlow    {
13146007Sthurlow 
13156007Sthurlow       // Check if the token exists
13166007Sthurlow       if ( ( nReturn = ASNDerCheckToken( pbTokenData, pbElements[nCtr],
13176007Sthurlow                                           0L, nRemainingTokenLength,
13186007Sthurlow                                           &nElementLength, &nActualTokenLength ) )
13196007Sthurlow                                 == SPNEGO_E_SUCCESS )
13206007Sthurlow       {
13216007Sthurlow 
13226007Sthurlow          // Token data should skip over the sequence token and then
13236007Sthurlow          // call the appropriate function to initialize the element
13246007Sthurlow          pbTokenData += nActualTokenLength;
13256007Sthurlow 
13266007Sthurlow          // Lengths in the elements should NOT go beyond the element
13276007Sthurlow          // length
13286007Sthurlow 
13296007Sthurlow          // Different tokens mean different elements
13306007Sthurlow          if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
13316007Sthurlow          {
13326007Sthurlow 
13336007Sthurlow             // Handle each element as appropriate
13346007Sthurlow             switch( pbElements[nCtr] )
13356007Sthurlow             {
13366007Sthurlow 
13376007Sthurlow                case SPNEGO_NEGINIT_ELEMENT_MECHTYPES:
13386007Sthurlow                {
13396007Sthurlow                   //
13406007Sthurlow                   // This is a Mech List that specifies which OIDs the
13416007Sthurlow                   // originator of the Init Token supports.
13426007Sthurlow                   //
13436007Sthurlow 
13446007Sthurlow                   nReturn = GetSpnegoInitTokenMechList( pbTokenData, nElementLength,
13456007Sthurlow                                                          &pSpnegoToken->aElementArray[nCtr] );
13466007Sthurlow 
13476007Sthurlow                }
13486007Sthurlow                break;
13496007Sthurlow 
13506007Sthurlow                case SPNEGO_NEGINIT_ELEMENT_REQFLAGS:
13516007Sthurlow                {
13526007Sthurlow                   //
13536007Sthurlow                   // This is a BITSTRING which specifies the flags that the receiver
13546007Sthurlow                   // pass to the gss_accept_sec_context() function.
13556007Sthurlow                   //
13566007Sthurlow 
13576007Sthurlow                   nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength,
13586007Sthurlow                                                                   BITSTRING, spnego_init_reqFlags,
13596007Sthurlow                                                                   &pSpnegoToken->aElementArray[nCtr] );
13606007Sthurlow                }
13616007Sthurlow                break;
13626007Sthurlow 
13636007Sthurlow                case SPNEGO_NEGINIT_ELEMENT_MECHTOKEN:
13646007Sthurlow                {
13656007Sthurlow                   //
13666007Sthurlow                   // This is an OCTETSTRING which contains a GSSAPI token corresponding
13676007Sthurlow                   // to the first OID in the MechList.
13686007Sthurlow                   //
13696007Sthurlow 
13706007Sthurlow                   nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength,
13716007Sthurlow                                                                   OCTETSTRING, spnego_init_mechToken,
13726007Sthurlow                                                                   &pSpnegoToken->aElementArray[nCtr] );
13736007Sthurlow               }
13746007Sthurlow                break;
13756007Sthurlow 
13766007Sthurlow                case SPNEGO_NEGINIT_ELEMENT_MECHLISTMIC:
13776007Sthurlow                {
13786007Sthurlow                   //
13796007Sthurlow                   // This is an OCTETSTRING which contains a message integrity BLOB.
13806007Sthurlow                   //
13816007Sthurlow 
13826007Sthurlow                   nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength,
13836007Sthurlow                                                                   OCTETSTRING, spnego_init_mechListMIC,
13846007Sthurlow                                                                   &pSpnegoToken->aElementArray[nCtr] );
13856007Sthurlow 		/*
13866007Sthurlow 		 * don't believe everything you read in RFCs (and MS
13876007Sthurlow 		 * sample code)...  win2k is sending not an octet string,
13886007Sthurlow 		 * but a "general string", wrapped in a sequence.
13896007Sthurlow 		 */
13906007Sthurlow 		if (nReturn != SPNEGO_E_UNEXPECTED_TYPE)
13916007Sthurlow 			break;
13926007Sthurlow          	ptok = pbTokenData;
13936007Sthurlow 		elen = nElementLength;
13946007Sthurlow 		if ((nReturn = ASNDerCheckToken(ptok, SPNEGO_CONSTRUCTED_SEQUENCE, elen, elen, &len, &tlen)) != SPNEGO_E_SUCCESS)
13956007Sthurlow 			break;
13966007Sthurlow 		elen -= tlen;
13976007Sthurlow 		ptok += tlen;
13986007Sthurlow 
13996007Sthurlow 		if ((nReturn = ASNDerCheckToken(ptok, SEQ_ELM(0), elen, elen, &len, &tlen)) != SPNEGO_E_SUCCESS)
14006007Sthurlow 			break;
14016007Sthurlow 		elen -= tlen;
14026007Sthurlow 		ptok += tlen;
14036007Sthurlow 		nReturn = InitSpnegoTokenElementFromBasicType(ptok, elen, GENERALSTR, spnego_init_mechListMIC, &pSpnegoToken->aElementArray[nCtr]);
14046007Sthurlow                }
14056007Sthurlow                break;
14066007Sthurlow 
14076007Sthurlow             }  // SWITCH Element
14086007Sthurlow          }
14096007Sthurlow          else
14106007Sthurlow          {
14116007Sthurlow 
14126007Sthurlow             switch( pbElements[nCtr] )
14136007Sthurlow             {
14146007Sthurlow 
14156007Sthurlow                case SPNEGO_NEGTARG_ELEMENT_NEGRESULT:
14166007Sthurlow                {
14176007Sthurlow                   //
14186007Sthurlow                   // This is an ENUMERATION which specifies result of the last GSS
14196007Sthurlow                   // token negotiation call.
14206007Sthurlow                   //
14216007Sthurlow 
14226007Sthurlow                   nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength,
14236007Sthurlow                                                                   ENUMERATED, spnego_targ_negResult,
14246007Sthurlow                                                                   &pSpnegoToken->aElementArray[nCtr] );
14256007Sthurlow                }
14266007Sthurlow                break;
14276007Sthurlow 
14286007Sthurlow                case SPNEGO_NEGTARG_ELEMENT_SUPPORTEDMECH:
14296007Sthurlow                {
14306007Sthurlow                   //
14316007Sthurlow                   // This is an OID which specifies a supported mechanism.
14326007Sthurlow                   //
14336007Sthurlow 
14346007Sthurlow                   nReturn = InitSpnegoTokenElementFromOID( pbTokenData, nElementLength,
14356007Sthurlow                                                            spnego_targ_mechListMIC,
14366007Sthurlow                                                            &pSpnegoToken->aElementArray[nCtr] );
14376007Sthurlow                }
14386007Sthurlow                break;
14396007Sthurlow 
14406007Sthurlow                case SPNEGO_NEGTARG_ELEMENT_RESPONSETOKEN:
14416007Sthurlow                {
14426007Sthurlow                   //
14436007Sthurlow                   // This is an OCTETSTRING which specifies results of the last GSS
14446007Sthurlow                   // token negotiation call.
14456007Sthurlow                   //
14466007Sthurlow 
14476007Sthurlow                   nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength,
14486007Sthurlow                                                                   OCTETSTRING, spnego_targ_responseToken,
14496007Sthurlow                                                                   &pSpnegoToken->aElementArray[nCtr] );
14506007Sthurlow                }
14516007Sthurlow                break;
14526007Sthurlow 
14536007Sthurlow                case SPNEGO_NEGTARG_ELEMENT_MECHLISTMIC:
14546007Sthurlow                {
14556007Sthurlow                   //
14566007Sthurlow                   // This is an OCTETSTRING which specifies a message integrity BLOB.
14576007Sthurlow                   //
14586007Sthurlow 
14596007Sthurlow                   nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength,
14606007Sthurlow                                                                   OCTETSTRING, spnego_targ_mechListMIC,
14616007Sthurlow                                                                   &pSpnegoToken->aElementArray[nCtr] );
14626007Sthurlow                }
14636007Sthurlow                break;
14646007Sthurlow 
14656007Sthurlow             }  // SWITCH Element
14666007Sthurlow 
14676007Sthurlow          }  // ELSE !NegTokenInit
14686007Sthurlow 
14696007Sthurlow          // Account for the entire token and following data
14706007Sthurlow          nRemainingTokenLength -= ( nActualTokenLength + nElementLength );
14716007Sthurlow 
14726007Sthurlow          // Token data should skip past the element length now
14736007Sthurlow          pbTokenData += nElementLength;
14746007Sthurlow 
14756007Sthurlow       }  // IF Token found
14766007Sthurlow       else if ( SPNEGO_E_TOKEN_NOT_FOUND == nReturn )
14776007Sthurlow       {
14786007Sthurlow          // For now, this is a benign error (remember, all elements are optional, so
14796007Sthurlow          // if we don't find one, it's okay).
14806007Sthurlow 
14816007Sthurlow          nReturn = SPNEGO_E_SUCCESS;
14826007Sthurlow       }
14836007Sthurlow 
14846007Sthurlow    }  // FOR enum elements
14856007Sthurlow 
14866007Sthurlow    //
14876007Sthurlow    // We should always run down to 0 remaining bytes in the token.  If not, we've got
14886007Sthurlow    // a bad token.
14896007Sthurlow    //
14906007Sthurlow 
14916007Sthurlow    if ( SPNEGO_E_SUCCESS == nReturn && nRemainingTokenLength != 0L )
14926007Sthurlow    {
14936007Sthurlow       nReturn = SPNEGO_E_INVALID_TOKEN;
14946007Sthurlow    }
14956007Sthurlow 
14966007Sthurlow    return nReturn;
14976007Sthurlow }
14986007Sthurlow 
14996007Sthurlow 
15006007Sthurlow /////////////////////////////////////////////////////////////////////////////
15016007Sthurlow //
15026007Sthurlow // Function:
15036007Sthurlow //    FindMechOIDInMechList
15046007Sthurlow //
15056007Sthurlow // Parameters:
15066007Sthurlow //    [in]  pSpnegoElement          -  SPNEGO_ELEMENT for MechList
15076007Sthurlow //    [in]  MechOID                 -  OID we're looking for.
15086007Sthurlow //    [out] piMechTypeIndex         -  Index in the list where OID was
15096007Sthurlow //                                     found
15106007Sthurlow //
15116007Sthurlow // Returns:
15126007Sthurlow //    int   Success - SPNEGO_E_SUCCESS
15136007Sthurlow //          Failure - SPNEGO API Error code
15146007Sthurlow //
15156007Sthurlow // Comments :
15166007Sthurlow //    Walks the MechList for MechOID.  When it is found, the index in the
15176007Sthurlow //    list is written to piMechTypeIndex.
15186007Sthurlow //
15196007Sthurlow ////////////////////////////////////////////////////////////////////////////
15206007Sthurlow 
FindMechOIDInMechList(SPNEGO_ELEMENT * pSpnegoElement,SPNEGO_MECH_OID MechOID,int * piMechTypeIndex)15216007Sthurlow int FindMechOIDInMechList( SPNEGO_ELEMENT* pSpnegoElement, SPNEGO_MECH_OID MechOID,
15226007Sthurlow                           int * piMechTypeIndex )
15236007Sthurlow {
15246007Sthurlow    int   nReturn = SPNEGO_E_NOT_FOUND;
15256007Sthurlow    int   nCtr = 0;
15266007Sthurlow    long  nLength = 0L;
15276007Sthurlow    long  nBoundaryLength = pSpnegoElement->nDatalength;
15286007Sthurlow    unsigned char* pbMechListData = pSpnegoElement->pbData;
15296007Sthurlow 
15306007Sthurlow    while( SPNEGO_E_SUCCESS != nReturn && nBoundaryLength > 0L )
15316007Sthurlow    {
15326007Sthurlow 
15336007Sthurlow       // Use the helper function to check the OID
15346007Sthurlow       if ( ( nReturn = ASNDerCheckOID( pbMechListData, MechOID, nBoundaryLength, &nLength ) )
15356007Sthurlow                      == SPNEGO_E_SUCCESS )
15366007Sthurlow       {
15376007Sthurlow          *piMechTypeIndex = nCtr;
15386007Sthurlow       }
15396007Sthurlow 
15406007Sthurlow       // Adjust for the current OID
15416007Sthurlow       pbMechListData += nLength;
15426007Sthurlow       nBoundaryLength -= nLength;
15436007Sthurlow       nCtr++;
15446007Sthurlow 
15456007Sthurlow    }  // WHILE enuming OIDs
15466007Sthurlow 
15476007Sthurlow    return nReturn;
15486007Sthurlow 
15496007Sthurlow }
15506007Sthurlow 
15516007Sthurlow 
15526007Sthurlow /////////////////////////////////////////////////////////////////////////////
15536007Sthurlow //
15546007Sthurlow // Function:
15556007Sthurlow //    ValidateMechList
15566007Sthurlow //
15576007Sthurlow // Parameters:
15586007Sthurlow //    [in]  pbMechListData          -  Pointer to binary MechList data
15596007Sthurlow //    [in]  nBoundaryLength         -  Length we must not exceed
15606007Sthurlow //
15616007Sthurlow // Returns:
15626007Sthurlow //    int   Success - SPNEGO_E_SUCCESS
15636007Sthurlow //          Failure - SPNEGO API Error code
15646007Sthurlow //
15656007Sthurlow // Comments :
15666007Sthurlow //    Checks the data at pbMechListData to see if it looks like a MechList.
15676007Sthurlow //    As part of this, we walk the list and ensure that none of the OIDs
15686007Sthurlow //    have a length that takes us outside of nBoundaryLength.
15696007Sthurlow //
15706007Sthurlow ////////////////////////////////////////////////////////////////////////////
15716007Sthurlow 
ValidateMechList(unsigned char * pbMechListData,long nBoundaryLength)15726007Sthurlow int ValidateMechList( unsigned char* pbMechListData, long nBoundaryLength )
15736007Sthurlow {
15746007Sthurlow    int   nReturn = SPNEGO_E_SUCCESS;
15756007Sthurlow    long  nLength = 0L;
15766007Sthurlow    long  nTokenLength = 0L;
15776007Sthurlow 
15786007Sthurlow    while( SPNEGO_E_SUCCESS == nReturn && nBoundaryLength > 0L )
15796007Sthurlow    {
15806007Sthurlow       // Verify that we have something that at least *looks* like an OID - in other
15816007Sthurlow       // words it has an OID identifier and specifies a length that doesn't go beyond
15826007Sthurlow       // the size of the list.
15836007Sthurlow       nReturn = ASNDerCheckToken( pbMechListData, OID, 0L, nBoundaryLength,
15846007Sthurlow                                   &nLength, &nTokenLength );
15856007Sthurlow 
15866007Sthurlow       // Adjust for the current OID
15876007Sthurlow       pbMechListData += ( nLength + nTokenLength );
15886007Sthurlow       nBoundaryLength -= ( nLength + nTokenLength );
15896007Sthurlow 
15906007Sthurlow    }  // WHILE enuming OIDs
15916007Sthurlow 
15926007Sthurlow    return nReturn;
15936007Sthurlow 
15946007Sthurlow }
15956007Sthurlow 
15966007Sthurlow /////////////////////////////////////////////////////////////////////////////
15976007Sthurlow //
15986007Sthurlow // Function:
15996007Sthurlow //    IsValidMechOid
16006007Sthurlow //
16016007Sthurlow // Parameters:
16026007Sthurlow //    [in]  mechOid  -  mechOID id enumeration
16036007Sthurlow //
16046007Sthurlow // Returns:
16056007Sthurlow //    int   Success - 1
16066007Sthurlow //          Failure - 0
16076007Sthurlow //
16086007Sthurlow // Comments :
16096007Sthurlow //    Checks for a valid mechOid value.
16106007Sthurlow //
16116007Sthurlow ////////////////////////////////////////////////////////////////////////////
16126007Sthurlow 
IsValidMechOid(SPNEGO_MECH_OID mechOid)16136007Sthurlow int IsValidMechOid( SPNEGO_MECH_OID mechOid )
16146007Sthurlow {
16156007Sthurlow    return ( mechOid >= spnego_mech_oid_Kerberos_V5_Legacy &&
1616*10023SGordon.Ross@Sun.COM             mechOid <= spnego_mech_oid_NTLMSSP );
16176007Sthurlow }
16186007Sthurlow 
16196007Sthurlow /////////////////////////////////////////////////////////////////////////////
16206007Sthurlow //
16216007Sthurlow // Function:
16226007Sthurlow //    IsValidContextFlags
16236007Sthurlow //
16246007Sthurlow // Parameters:
16256007Sthurlow //    [in]  ucContextFlags -  ContextFlags value
16266007Sthurlow //
16276007Sthurlow // Returns:
16286007Sthurlow //    int   Success - 1
16296007Sthurlow //          Failure - 0
16306007Sthurlow //
16316007Sthurlow // Comments :
16326007Sthurlow //    Checks for a valid ContextFlags value.
16336007Sthurlow //
16346007Sthurlow ////////////////////////////////////////////////////////////////////////////
16356007Sthurlow 
IsValidContextFlags(unsigned char ucContextFlags)16366007Sthurlow int IsValidContextFlags( unsigned char ucContextFlags )
16376007Sthurlow {
16386007Sthurlow    // Mask out our valid bits.  If there is anything leftover, this
16396007Sthurlow    // is not a valid value for Context Flags
16406007Sthurlow    return ( ( ucContextFlags & ~SPNEGO_NEGINIT_CONTEXT_MASK ) == 0 );
16416007Sthurlow }
16426007Sthurlow 
16436007Sthurlow /////////////////////////////////////////////////////////////////////////////
16446007Sthurlow //
16456007Sthurlow // Function:
16466007Sthurlow //    IsValidNegResult
16476007Sthurlow //
16486007Sthurlow // Parameters:
16496007Sthurlow //    [in]  negResult   -  NegResult value
16506007Sthurlow //
16516007Sthurlow // Returns:
16526007Sthurlow //    int   Success - 1
16536007Sthurlow //          Failure - 0
16546007Sthurlow //
16556007Sthurlow // Comments :
16566007Sthurlow //    Checks for a valid NegResult value.
16576007Sthurlow //
16586007Sthurlow ////////////////////////////////////////////////////////////////////////////
16596007Sthurlow 
IsValidNegResult(SPNEGO_NEGRESULT negResult)16606007Sthurlow int IsValidNegResult( SPNEGO_NEGRESULT negResult )
16616007Sthurlow {
16626007Sthurlow    return ( negResult >= spnego_negresult_success &&
16636007Sthurlow             negResult <= spnego_negresult_rejected );
16646007Sthurlow }
16656007Sthurlow 
16666007Sthurlow /////////////////////////////////////////////////////////////////////////////
16676007Sthurlow //
16686007Sthurlow // Function:
16696007Sthurlow //    IsValidSpnegoToken
16706007Sthurlow //
16716007Sthurlow // Parameters:
16726007Sthurlow //    [in]  pSpnegoToken   -  Points to SPNEGO_TOKEN data structure
16736007Sthurlow //
16746007Sthurlow // Returns:
16756007Sthurlow //    int   Success - 1
16766007Sthurlow //          Failure - 0
16776007Sthurlow //
16786007Sthurlow // Comments :
16796007Sthurlow //    Performs simple heuristic on location pointed to by pSpnegoToken.
16806007Sthurlow //
16816007Sthurlow ////////////////////////////////////////////////////////////////////////////
16826007Sthurlow 
IsValidSpnegoToken(SPNEGO_TOKEN * pSpnegoToken)16836007Sthurlow int IsValidSpnegoToken( SPNEGO_TOKEN* pSpnegoToken )
16846007Sthurlow {
16856007Sthurlow    int   nReturn = 0;
16866007Sthurlow 
16876007Sthurlow    // Parameter should be non-NULL
16886007Sthurlow    if ( NULL != pSpnegoToken )
16896007Sthurlow    {
16906007Sthurlow       // Length should be at least the size defined in the header
16916007Sthurlow       if ( pSpnegoToken->nStructSize >= SPNEGO_TOKEN_SIZE )
16926007Sthurlow       {
16936007Sthurlow          // Number of elements should be >= our maximum - if it's greater, that's
16946007Sthurlow          // okay, since we'll only be accessing the elements up to MAX_NUM_TOKEN_ELEMENTS
16956007Sthurlow          if ( pSpnegoToken->nNumElements >= MAX_NUM_TOKEN_ELEMENTS )
16966007Sthurlow          {
16976007Sthurlow             // Check for proper token type
16986007Sthurlow             if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType ||
16996007Sthurlow                SPNEGO_TOKEN_TARG == pSpnegoToken->ucTokenType )
17006007Sthurlow             {
17016007Sthurlow                nReturn = 1;
17026007Sthurlow             }
17036007Sthurlow          }
17046007Sthurlow 
17056007Sthurlow       }  // IF struct size makes sense
17066007Sthurlow 
17076007Sthurlow    }  // IF non-NULL spnego Token
17086007Sthurlow 
17096007Sthurlow    return nReturn;
17106007Sthurlow }
17116007Sthurlow 
17126007Sthurlow /////////////////////////////////////////////////////////////////////////////
17136007Sthurlow //
17146007Sthurlow // Function:
17156007Sthurlow //    IsValidSpnegoElement
17166007Sthurlow //
17176007Sthurlow // Parameters:
17186007Sthurlow //    [in]  pSpnegoToken   -  Points to SPNEGO_TOKEN data structure
17196007Sthurlow //    [in]  spnegoElement  -  spnegoElement Type from enumeration
17206007Sthurlow //
17216007Sthurlow // Returns:
17226007Sthurlow //    int   Success - 1
17236007Sthurlow //          Failure - 0
17246007Sthurlow //
17256007Sthurlow // Comments :
17266007Sthurlow //    Checks that spnegoElement has a valid value and is appropriate for
17276007Sthurlow //    the SPNEGO token encapsulated by pSpnegoToken.
17286007Sthurlow //
17296007Sthurlow ////////////////////////////////////////////////////////////////////////////
17306007Sthurlow 
IsValidSpnegoElement(SPNEGO_TOKEN * pSpnegoToken,SPNEGO_ELEMENT_TYPE spnegoElement)17316007Sthurlow int IsValidSpnegoElement( SPNEGO_TOKEN* pSpnegoToken,SPNEGO_ELEMENT_TYPE spnegoElement )
17326007Sthurlow {
17336007Sthurlow    int   nReturn = 0;
17346007Sthurlow 
17356007Sthurlow    // Check boundaries
17366007Sthurlow    if ( spnegoElement > spnego_element_min &&
17376007Sthurlow       spnegoElement < spnego_element_max )
17386007Sthurlow    {
17396007Sthurlow 
17406007Sthurlow       // Check for appropriateness to token type
17416007Sthurlow       if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
17426007Sthurlow       {
17436007Sthurlow          nReturn = ( spnegoElement >= spnego_init_mechtypes &&
17446007Sthurlow                      spnegoElement <= spnego_init_mechListMIC );
17456007Sthurlow       }
17466007Sthurlow       else
17476007Sthurlow       {
17486007Sthurlow          nReturn = ( spnegoElement >= spnego_targ_negResult &&
17496007Sthurlow                      spnegoElement <= spnego_targ_mechListMIC );
17506007Sthurlow       }
17516007Sthurlow 
17526007Sthurlow    }  // IF boundary conditions are met
17536007Sthurlow 
17546007Sthurlow    return nReturn;
17556007Sthurlow }
17566007Sthurlow 
17576007Sthurlow /////////////////////////////////////////////////////////////////////////////
17586007Sthurlow //
17596007Sthurlow // Function:
17606007Sthurlow //    CalculateElementArrayIndex
17616007Sthurlow //
17626007Sthurlow // Parameters:
17636007Sthurlow //    [in]  pSpnegoToken   -  Points to SPNEGO_TOKEN data structure
17646007Sthurlow //    [in]  spnegoElement  -  spnegoElement Type from enumeration
17656007Sthurlow //
17666007Sthurlow // Returns:
17676007Sthurlow //    int   index in the SPNEGO_TOKEN element array that the element can
17686007Sthurlow //          can be found
17696007Sthurlow //
17706007Sthurlow // Comments :
17716007Sthurlow //    Based on the Token Type, calculates the index in the element array
17726007Sthurlow //    at which the specified element can be found.
17736007Sthurlow //
17746007Sthurlow ////////////////////////////////////////////////////////////////////////////
17756007Sthurlow 
CalculateElementArrayIndex(SPNEGO_TOKEN * pSpnegoToken,SPNEGO_ELEMENT_TYPE spnegoElement)17766007Sthurlow int CalculateElementArrayIndex( SPNEGO_TOKEN* pSpnegoToken,SPNEGO_ELEMENT_TYPE spnegoElement )
17776007Sthurlow {
17786007Sthurlow    int   nReturn = 0;
17796007Sthurlow 
17806007Sthurlow    // Offset is difference between value and initial element identifier
17816007Sthurlow    // (these differ based on ucTokenType)
17826007Sthurlow 
17836007Sthurlow    if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
17846007Sthurlow    {
17856007Sthurlow       nReturn = spnegoElement - spnego_init_mechtypes;
17866007Sthurlow    }
17876007Sthurlow    else
17886007Sthurlow    {
17896007Sthurlow       nReturn = spnegoElement - spnego_targ_negResult;
17906007Sthurlow    }
17916007Sthurlow 
17926007Sthurlow    return nReturn;
17936007Sthurlow }
17946007Sthurlow 
17956007Sthurlow /////////////////////////////////////////////////////////////////////////////
17966007Sthurlow //
17976007Sthurlow // Function:
17986007Sthurlow //    InitTokenFromBinary
17996007Sthurlow //
18006007Sthurlow // Parameters:
18016007Sthurlow //    [in]  ucCopyData     -  Flag indicating if data should be copied
18026007Sthurlow //    [in]  ulFlags        -  Flags value for structure
18036007Sthurlow //    [in]  pnTokenData    -  Binary Token Data
18046007Sthurlow //    [in]  ulLength       -  Length of the data
18056007Sthurlow //    [out] ppSpnegoToken  -  Pointer to call allocated SPNEGO Token
18066007Sthurlow //                            data structure
18076007Sthurlow //
18086007Sthurlow // Returns:
18096007Sthurlow //    int   Success - SPNEGO_E_SUCCESS
18106007Sthurlow //          Failure - SPNEGO API Error code
18116007Sthurlow //
18126007Sthurlow // Comments :
18136007Sthurlow //    Allocates a SPNEGO_TOKEN data structure and fills it out as
18146007Sthurlow //    appropriate based in the flags passed into the function.
18156007Sthurlow //
18166007Sthurlow ////////////////////////////////////////////////////////////////////////////
18176007Sthurlow 
18186007Sthurlow 
18196007Sthurlow // 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)18206007Sthurlow int InitTokenFromBinary( unsigned char ucCopyData, unsigned long ulFlags,
18216007Sthurlow                         unsigned char* pbTokenData, unsigned long ulLength,
18226007Sthurlow                         SPNEGO_TOKEN** ppSpnegoToken )
18236007Sthurlow {
18246007Sthurlow    int            nReturn = SPNEGO_E_INVALID_PARAMETER;
18256007Sthurlow    SPNEGO_TOKEN*  pSpnegoToken = NULL;
18266007Sthurlow    unsigned char* pbFirstElement = NULL;
18276007Sthurlow    long           nTokenLength = 0L;
18286007Sthurlow    long           nRemainingTokenLength = 0L;
18296007Sthurlow 
18306007Sthurlow    // Basic Parameter Validation
18316007Sthurlow 
18326007Sthurlow    if (  NULL != pbTokenData &&
18336007Sthurlow          NULL != ppSpnegoToken &&
18346007Sthurlow          0L != ulLength )
18356007Sthurlow    {
18366007Sthurlow 
18376007Sthurlow       //
18386007Sthurlow       // Allocate the empty token, then initialize the data structure.
18396007Sthurlow       //
18406007Sthurlow 
18416007Sthurlow       pSpnegoToken = AllocEmptySpnegoToken( ucCopyData, ulFlags, pbTokenData, ulLength );
18426007Sthurlow 
18436007Sthurlow       if ( NULL != pSpnegoToken )
18446007Sthurlow       {
18456007Sthurlow 
18466007Sthurlow          // Copy the binary data locally
18476007Sthurlow 
18486007Sthurlow 
18496007Sthurlow          // Initialize the token type
18506007Sthurlow          if ( ( nReturn = InitSpnegoTokenType( pSpnegoToken, &nTokenLength,
18516007Sthurlow                                                 &nRemainingTokenLength, &pbFirstElement ) )
18526007Sthurlow                         == SPNEGO_E_SUCCESS )
18536007Sthurlow          {
18546007Sthurlow 
18556007Sthurlow             // Initialize the element array
18566007Sthurlow             if ( ( nReturn = InitSpnegoTokenElements( pSpnegoToken, pbFirstElement,
18576007Sthurlow                                                       nRemainingTokenLength ) )
18586007Sthurlow                            == SPNEGO_E_SUCCESS )
18596007Sthurlow             {
18606007Sthurlow                *ppSpnegoToken = pSpnegoToken;
18616007Sthurlow             }
18626007Sthurlow 
18636007Sthurlow          }  // IF Init Token Type
18646007Sthurlow 
18656007Sthurlow          // Cleanup on error condition
18666007Sthurlow          if ( SPNEGO_E_SUCCESS != nReturn )
18676007Sthurlow          {
18686007Sthurlow             spnegoFreeData( pSpnegoToken );
18696007Sthurlow          }
18706007Sthurlow 
18716007Sthurlow       }
18726007Sthurlow       else
18736007Sthurlow       {
18746007Sthurlow          nReturn = SPNEGO_E_OUT_OF_MEMORY;
18756007Sthurlow       }
18766007Sthurlow 
18776007Sthurlow    }  // IF Valid parameters
18786007Sthurlow 
18796007Sthurlow 
18806007Sthurlow    return nReturn;
18816007Sthurlow }
1882