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