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