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