1*4bff34e3Sthurlow // Copyright (C) 2002 Microsoft Corporation 2*4bff34e3Sthurlow // All rights reserved. 3*4bff34e3Sthurlow // 4*4bff34e3Sthurlow // THIS CODE AND INFORMATION IS PROVIDED "AS IS" 5*4bff34e3Sthurlow // WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 6*4bff34e3Sthurlow // OR IMPLIED, INCLUDING BUT NOT LIMITED 7*4bff34e3Sthurlow // TO THE IMPLIED WARRANTIES OF MERCHANTIBILITY 8*4bff34e3Sthurlow // AND/OR FITNESS FOR A PARTICULAR PURPOSE. 9*4bff34e3Sthurlow // 10*4bff34e3Sthurlow // Date - 10/08/2002 11*4bff34e3Sthurlow // Author - Sanj Surati 12*4bff34e3Sthurlow 13*4bff34e3Sthurlow ///////////////////////////////////////////////////////////// 14*4bff34e3Sthurlow // 15*4bff34e3Sthurlow // SPNEGOPARSE.C 16*4bff34e3Sthurlow // 17*4bff34e3Sthurlow // SPNEGO Token Handler Source File 18*4bff34e3Sthurlow // 19*4bff34e3Sthurlow // Contains implementation of SPNEGO Token parsing functions. 20*4bff34e3Sthurlow // 21*4bff34e3Sthurlow ///////////////////////////////////////////////////////////// 22*4bff34e3Sthurlow 23*4bff34e3Sthurlow #pragma ident "%Z%%M% %I% %E% SMI" 24*4bff34e3Sthurlow 25*4bff34e3Sthurlow #include <stdlib.h> 26*4bff34e3Sthurlow #include <stdio.h> 27*4bff34e3Sthurlow #include <memory.h> 28*4bff34e3Sthurlow #include "spnego.h" 29*4bff34e3Sthurlow #include "derparse.h" 30*4bff34e3Sthurlow #include "spnegoparse.h" 31*4bff34e3Sthurlow 32*4bff34e3Sthurlow // 33*4bff34e3Sthurlow // Defined in DERPARSE.C 34*4bff34e3Sthurlow // 35*4bff34e3Sthurlow 36*4bff34e3Sthurlow extern MECH_OID g_stcMechOIDList []; 37*4bff34e3Sthurlow 38*4bff34e3Sthurlow /**********************************************************************/ 39*4bff34e3Sthurlow /** **/ 40*4bff34e3Sthurlow /** **/ 41*4bff34e3Sthurlow /** **/ 42*4bff34e3Sthurlow /** **/ 43*4bff34e3Sthurlow /** Local SPNEGO Helper definitions **/ 44*4bff34e3Sthurlow /** **/ 45*4bff34e3Sthurlow /** **/ 46*4bff34e3Sthurlow /** **/ 47*4bff34e3Sthurlow /** **/ 48*4bff34e3Sthurlow /**********************************************************************/ 49*4bff34e3Sthurlow 50*4bff34e3Sthurlow 51*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 52*4bff34e3Sthurlow // 53*4bff34e3Sthurlow // Function: 54*4bff34e3Sthurlow // CalculateMinSpnegoInitTokenSize 55*4bff34e3Sthurlow // 56*4bff34e3Sthurlow // Parameters: 57*4bff34e3Sthurlow // [in] nMechTokenLength - Length of the MechToken Element 58*4bff34e3Sthurlow // [in] nMechListMICLength - Length of the MechListMIC Element 59*4bff34e3Sthurlow // [in] mechOID - OID for MechList 60*4bff34e3Sthurlow // [in] nReqFlagsAvailable - Is ContextFlags element available 61*4bff34e3Sthurlow // [out] pnTokenSize - Filled out with total size of token 62*4bff34e3Sthurlow // [out] pnInternalTokenLength - Filled out with length minus length 63*4bff34e3Sthurlow // for initial token. 64*4bff34e3Sthurlow // 65*4bff34e3Sthurlow // Returns: 66*4bff34e3Sthurlow // int Success - SPNEGO_E_SUCCESS 67*4bff34e3Sthurlow // Failure - SPNEGO API Error code 68*4bff34e3Sthurlow // 69*4bff34e3Sthurlow // Comments : 70*4bff34e3Sthurlow // Calculates the required length for a SPNEGO NegTokenInit token based 71*4bff34e3Sthurlow // on the supplied variable length values and which elements are present. 72*4bff34e3Sthurlow // Note that because the lengths can be represented by an arbitrary 73*4bff34e3Sthurlow // number of bytes in DER encodings, we actually calculate the lengths 74*4bff34e3Sthurlow // backwards, so we always know how many bytes we will potentially be 75*4bff34e3Sthurlow // writing out. 76*4bff34e3Sthurlow // 77*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 78*4bff34e3Sthurlow 79*4bff34e3Sthurlow int CalculateMinSpnegoInitTokenSize( long nMechTokenLength, 80*4bff34e3Sthurlow long nMechListMICLength, SPNEGO_MECH_OID mechOid, 81*4bff34e3Sthurlow int nReqFlagsAvailable, long* pnTokenSize, 82*4bff34e3Sthurlow long* pnInternalTokenLength ) 83*4bff34e3Sthurlow { 84*4bff34e3Sthurlow int nReturn = SPNEGO_E_INVALID_LENGTH; 85*4bff34e3Sthurlow 86*4bff34e3Sthurlow // Start at 0. 87*4bff34e3Sthurlow long nTotalLength = 0; 88*4bff34e3Sthurlow long nTempLength= 0L; 89*4bff34e3Sthurlow 90*4bff34e3Sthurlow // We will calculate this by walking the token backwards 91*4bff34e3Sthurlow 92*4bff34e3Sthurlow // Start with MIC Element 93*4bff34e3Sthurlow if ( nMechListMICLength > 0L ) 94*4bff34e3Sthurlow { 95*4bff34e3Sthurlow nTempLength = ASNDerCalcElementLength( nMechListMICLength, NULL ); 96*4bff34e3Sthurlow 97*4bff34e3Sthurlow // Check for rollover error 98*4bff34e3Sthurlow if ( nTempLength < nMechListMICLength ) 99*4bff34e3Sthurlow { 100*4bff34e3Sthurlow goto xEndTokenInitLength; 101*4bff34e3Sthurlow } 102*4bff34e3Sthurlow 103*4bff34e3Sthurlow nTotalLength += nTempLength; 104*4bff34e3Sthurlow } 105*4bff34e3Sthurlow 106*4bff34e3Sthurlow // Next is the MechToken 107*4bff34e3Sthurlow if ( nMechTokenLength > 0L ) 108*4bff34e3Sthurlow { 109*4bff34e3Sthurlow nTempLength += ASNDerCalcElementLength( nMechTokenLength, NULL ); 110*4bff34e3Sthurlow 111*4bff34e3Sthurlow // Check for rollover error 112*4bff34e3Sthurlow if ( nTempLength < nTotalLength ) 113*4bff34e3Sthurlow { 114*4bff34e3Sthurlow goto xEndTokenInitLength; 115*4bff34e3Sthurlow } 116*4bff34e3Sthurlow 117*4bff34e3Sthurlow nTotalLength = nTempLength; 118*4bff34e3Sthurlow } 119*4bff34e3Sthurlow 120*4bff34e3Sthurlow // Next is the ReqFlags 121*4bff34e3Sthurlow if ( nReqFlagsAvailable ) 122*4bff34e3Sthurlow { 123*4bff34e3Sthurlow nTempLength += ASNDerCalcElementLength( SPNEGO_NEGINIT_MAXLEN_REQFLAGS, NULL ); 124*4bff34e3Sthurlow 125*4bff34e3Sthurlow // Check for rollover error 126*4bff34e3Sthurlow if ( nTempLength < nTotalLength ) 127*4bff34e3Sthurlow { 128*4bff34e3Sthurlow goto xEndTokenInitLength; 129*4bff34e3Sthurlow } 130*4bff34e3Sthurlow 131*4bff34e3Sthurlow nTotalLength = nTempLength; 132*4bff34e3Sthurlow } 133*4bff34e3Sthurlow 134*4bff34e3Sthurlow // Next is the MechList - This is REQUIRED 135*4bff34e3Sthurlow nTempLength += ASNDerCalcMechListLength( mechOid, NULL ); 136*4bff34e3Sthurlow 137*4bff34e3Sthurlow // Check for rollover error 138*4bff34e3Sthurlow if ( nTempLength < nTotalLength ) 139*4bff34e3Sthurlow { 140*4bff34e3Sthurlow goto xEndTokenInitLength; 141*4bff34e3Sthurlow } 142*4bff34e3Sthurlow 143*4bff34e3Sthurlow nTotalLength = nTempLength; 144*4bff34e3Sthurlow 145*4bff34e3Sthurlow // Following four fields are the basic header tokens 146*4bff34e3Sthurlow 147*4bff34e3Sthurlow // Sequence Token 148*4bff34e3Sthurlow nTempLength += ASNDerCalcTokenLength( nTotalLength, 0L ); 149*4bff34e3Sthurlow 150*4bff34e3Sthurlow // Check for rollover error 151*4bff34e3Sthurlow if ( nTempLength < nTotalLength ) 152*4bff34e3Sthurlow { 153*4bff34e3Sthurlow goto xEndTokenInitLength; 154*4bff34e3Sthurlow } 155*4bff34e3Sthurlow 156*4bff34e3Sthurlow nTotalLength = nTempLength; 157*4bff34e3Sthurlow 158*4bff34e3Sthurlow // Neg Token Identifier Token 159*4bff34e3Sthurlow nTempLength += ASNDerCalcTokenLength( nTotalLength, 0L ); 160*4bff34e3Sthurlow 161*4bff34e3Sthurlow // Check for rollover error 162*4bff34e3Sthurlow if ( nTempLength < nTotalLength ) 163*4bff34e3Sthurlow { 164*4bff34e3Sthurlow goto xEndTokenInitLength; 165*4bff34e3Sthurlow } 166*4bff34e3Sthurlow 167*4bff34e3Sthurlow nTotalLength = nTempLength; 168*4bff34e3Sthurlow 169*4bff34e3Sthurlow // SPNEGO OID Token 170*4bff34e3Sthurlow nTempLength += g_stcMechOIDList[spnego_mech_oid_Spnego].iLen; 171*4bff34e3Sthurlow 172*4bff34e3Sthurlow // Check for rollover error 173*4bff34e3Sthurlow if ( nTempLength < nTotalLength ) 174*4bff34e3Sthurlow { 175*4bff34e3Sthurlow goto xEndTokenInitLength; 176*4bff34e3Sthurlow } 177*4bff34e3Sthurlow 178*4bff34e3Sthurlow nTotalLength = nTempLength; 179*4bff34e3Sthurlow 180*4bff34e3Sthurlow // App Constructed Token 181*4bff34e3Sthurlow nTempLength += ASNDerCalcTokenLength( nTotalLength, 0L ); 182*4bff34e3Sthurlow 183*4bff34e3Sthurlow // Check for rollover error 184*4bff34e3Sthurlow if ( nTempLength < nTotalLength ) 185*4bff34e3Sthurlow { 186*4bff34e3Sthurlow goto xEndTokenInitLength; 187*4bff34e3Sthurlow } 188*4bff34e3Sthurlow 189*4bff34e3Sthurlow // The internal length doesn't include the number of bytes 190*4bff34e3Sthurlow // for the initial token 191*4bff34e3Sthurlow *pnInternalTokenLength = nTotalLength; 192*4bff34e3Sthurlow nTotalLength = nTempLength; 193*4bff34e3Sthurlow 194*4bff34e3Sthurlow // We're done 195*4bff34e3Sthurlow *pnTokenSize = nTotalLength; 196*4bff34e3Sthurlow nReturn = SPNEGO_E_SUCCESS; 197*4bff34e3Sthurlow 198*4bff34e3Sthurlow xEndTokenInitLength: 199*4bff34e3Sthurlow 200*4bff34e3Sthurlow return nReturn; 201*4bff34e3Sthurlow 202*4bff34e3Sthurlow } 203*4bff34e3Sthurlow 204*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 205*4bff34e3Sthurlow // 206*4bff34e3Sthurlow // Function: 207*4bff34e3Sthurlow // CreateSpnegoInitToken 208*4bff34e3Sthurlow // 209*4bff34e3Sthurlow // Parameters: 210*4bff34e3Sthurlow // [in] MechType - OID in MechList 211*4bff34e3Sthurlow // [in] ucContextFlags - ContextFlags value 212*4bff34e3Sthurlow // [in] pbMechToken - Mech Token Binary Data 213*4bff34e3Sthurlow // [in] ulMechTokenLen - Length of Mech Token 214*4bff34e3Sthurlow // [in] pbMechListMIC - MechListMIC Binary Data 215*4bff34e3Sthurlow // [in] ulMechListMICn - Length of MechListMIC 216*4bff34e3Sthurlow // [out] pbTokenData - Buffer to write token into. 217*4bff34e3Sthurlow // [in] nTokenLength - Length of pbTokenData buffer 218*4bff34e3Sthurlow // [in] nInternalTokenLength - Length of full token without leading 219*4bff34e3Sthurlow // token bytes. 220*4bff34e3Sthurlow // 221*4bff34e3Sthurlow // Returns: 222*4bff34e3Sthurlow // int Success - SPNEGO_E_SUCCESS 223*4bff34e3Sthurlow // Failure - SPNEGO API Error code 224*4bff34e3Sthurlow // 225*4bff34e3Sthurlow // Comments : 226*4bff34e3Sthurlow // Uses DER to fill out pbTokenData with a SPNEGO NegTokenInit Token 227*4bff34e3Sthurlow // Note that because the lengths can be represented by an arbitrary 228*4bff34e3Sthurlow // number of bytes in DER encodings, we actually calculate the lengths 229*4bff34e3Sthurlow // backwards, so we always know how many bytes we will potentially be 230*4bff34e3Sthurlow // writing out. 231*4bff34e3Sthurlow // 232*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 233*4bff34e3Sthurlow 234*4bff34e3Sthurlow int CreateSpnegoInitToken( SPNEGO_MECH_OID MechType, 235*4bff34e3Sthurlow unsigned char ucContextFlags, unsigned char* pbMechToken, 236*4bff34e3Sthurlow unsigned long ulMechTokenLen, unsigned char* pbMechListMIC, 237*4bff34e3Sthurlow unsigned long ulMechListMICLen, unsigned char* pbTokenData, 238*4bff34e3Sthurlow long nTokenLength, long nInternalTokenLength ) 239*4bff34e3Sthurlow { 240*4bff34e3Sthurlow int nReturn = SPNEGO_E_INVALID_LENGTH; 241*4bff34e3Sthurlow 242*4bff34e3Sthurlow // Start at 0. 243*4bff34e3Sthurlow long nTempLength= 0L; 244*4bff34e3Sthurlow long nTotalBytesWritten = 0L; 245*4bff34e3Sthurlow long nInternalLength = 0L; 246*4bff34e3Sthurlow 247*4bff34e3Sthurlow unsigned char* pbWriteTokenData = pbTokenData + nTokenLength; 248*4bff34e3Sthurlow 249*4bff34e3Sthurlow // Temporary buffer to hold the REQ Flags as BIT String Data 250*4bff34e3Sthurlow unsigned char abTempReqFlags[SPNEGO_NEGINIT_MAXLEN_REQFLAGS]; 251*4bff34e3Sthurlow 252*4bff34e3Sthurlow 253*4bff34e3Sthurlow // We will write the token out backwards to properly handle the cases 254*4bff34e3Sthurlow // where the length bytes become adjustable 255*4bff34e3Sthurlow 256*4bff34e3Sthurlow // Start with MIC Element 257*4bff34e3Sthurlow if ( ulMechListMICLen > 0L ) 258*4bff34e3Sthurlow { 259*4bff34e3Sthurlow nTempLength = ASNDerCalcElementLength( ulMechListMICLen, &nInternalLength ); 260*4bff34e3Sthurlow 261*4bff34e3Sthurlow // Decrease the pbWriteTokenData, now we know the length and 262*4bff34e3Sthurlow // write it out. 263*4bff34e3Sthurlow 264*4bff34e3Sthurlow pbWriteTokenData -= nTempLength; 265*4bff34e3Sthurlow nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGINIT_ELEMENT_MECHLISTMIC, 266*4bff34e3Sthurlow OCTETSTRING, pbMechListMIC, ulMechListMICLen ); 267*4bff34e3Sthurlow 268*4bff34e3Sthurlow // Adjust Values and sanity check 269*4bff34e3Sthurlow nTotalBytesWritten += nTempLength; 270*4bff34e3Sthurlow nInternalTokenLength -= nTempLength; 271*4bff34e3Sthurlow 272*4bff34e3Sthurlow if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 ) 273*4bff34e3Sthurlow { 274*4bff34e3Sthurlow goto xEndWriteNegTokenInit; 275*4bff34e3Sthurlow } 276*4bff34e3Sthurlow 277*4bff34e3Sthurlow } // IF MechListMIC is present 278*4bff34e3Sthurlow 279*4bff34e3Sthurlow // Next is the MechToken 280*4bff34e3Sthurlow if ( ulMechTokenLen > 0L ) 281*4bff34e3Sthurlow { 282*4bff34e3Sthurlow nTempLength = ASNDerCalcElementLength( ulMechTokenLen, &nInternalLength ); 283*4bff34e3Sthurlow 284*4bff34e3Sthurlow // Decrease the pbWriteTokenData, now we know the length and 285*4bff34e3Sthurlow // write it out. 286*4bff34e3Sthurlow pbWriteTokenData -= nTempLength; 287*4bff34e3Sthurlow nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGINIT_ELEMENT_MECHTOKEN, 288*4bff34e3Sthurlow OCTETSTRING, pbMechToken, ulMechTokenLen ); 289*4bff34e3Sthurlow // Adjust Values and sanity check 290*4bff34e3Sthurlow nTotalBytesWritten += nTempLength; 291*4bff34e3Sthurlow nInternalTokenLength -= nTempLength; 292*4bff34e3Sthurlow 293*4bff34e3Sthurlow if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 ) 294*4bff34e3Sthurlow { 295*4bff34e3Sthurlow goto xEndWriteNegTokenInit; 296*4bff34e3Sthurlow } 297*4bff34e3Sthurlow 298*4bff34e3Sthurlow } // IF MechToken Length is present 299*4bff34e3Sthurlow 300*4bff34e3Sthurlow // Next is the ReqFlags 301*4bff34e3Sthurlow if ( ucContextFlags > 0L ) 302*4bff34e3Sthurlow { 303*4bff34e3Sthurlow 304*4bff34e3Sthurlow nTempLength = ASNDerCalcElementLength( SPNEGO_NEGINIT_MAXLEN_REQFLAGS, &nInternalLength ); 305*4bff34e3Sthurlow 306*4bff34e3Sthurlow // We need a byte that indicates how many bits difference between the number 307*4bff34e3Sthurlow // of bits used in final octet (we only have one) and the max (8) 308*4bff34e3Sthurlow 309*4bff34e3Sthurlow abTempReqFlags[0] = SPNEGO_NEGINIT_REQFLAGS_BITDIFF; 310*4bff34e3Sthurlow abTempReqFlags[1] = ucContextFlags; 311*4bff34e3Sthurlow 312*4bff34e3Sthurlow // Decrease the pbWriteTokenData, now we know the length and 313*4bff34e3Sthurlow // write it out. 314*4bff34e3Sthurlow pbWriteTokenData -= nTempLength; 315*4bff34e3Sthurlow nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGINIT_ELEMENT_REQFLAGS, 316*4bff34e3Sthurlow BITSTRING, abTempReqFlags, SPNEGO_NEGINIT_MAXLEN_REQFLAGS ); 317*4bff34e3Sthurlow 318*4bff34e3Sthurlow // Adjust Values and sanity check 319*4bff34e3Sthurlow nTotalBytesWritten += nTempLength; 320*4bff34e3Sthurlow nInternalTokenLength -= nTempLength; 321*4bff34e3Sthurlow 322*4bff34e3Sthurlow if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 ) 323*4bff34e3Sthurlow { 324*4bff34e3Sthurlow goto xEndWriteNegTokenInit; 325*4bff34e3Sthurlow } 326*4bff34e3Sthurlow 327*4bff34e3Sthurlow } // IF ContextFlags 328*4bff34e3Sthurlow 329*4bff34e3Sthurlow // Next is the MechList - This is REQUIRED 330*4bff34e3Sthurlow nTempLength = ASNDerCalcMechListLength( MechType, &nInternalLength ); 331*4bff34e3Sthurlow 332*4bff34e3Sthurlow // Decrease the pbWriteTokenData, now we know the length and 333*4bff34e3Sthurlow // write it out. 334*4bff34e3Sthurlow pbWriteTokenData -= nTempLength; 335*4bff34e3Sthurlow nTempLength = ASNDerWriteMechList( pbWriteTokenData, MechType ); 336*4bff34e3Sthurlow 337*4bff34e3Sthurlow // Adjust Values and sanity check 338*4bff34e3Sthurlow nTotalBytesWritten += nTempLength; 339*4bff34e3Sthurlow nInternalTokenLength -= nTempLength; 340*4bff34e3Sthurlow 341*4bff34e3Sthurlow if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 ) 342*4bff34e3Sthurlow { 343*4bff34e3Sthurlow goto xEndWriteNegTokenInit; 344*4bff34e3Sthurlow } 345*4bff34e3Sthurlow 346*4bff34e3Sthurlow // The next tokens we're writing out reflect the total number of bytes 347*4bff34e3Sthurlow // we have actually written out. 348*4bff34e3Sthurlow 349*4bff34e3Sthurlow // Sequence Token 350*4bff34e3Sthurlow nTempLength = ASNDerCalcTokenLength( nTotalBytesWritten, 0L ); 351*4bff34e3Sthurlow 352*4bff34e3Sthurlow // Decrease the pbWriteTokenData, now we know the length and 353*4bff34e3Sthurlow // write it out. 354*4bff34e3Sthurlow pbWriteTokenData -= nTempLength; 355*4bff34e3Sthurlow nTempLength = ASNDerWriteToken( pbWriteTokenData, SPNEGO_CONSTRUCTED_SEQUENCE, 356*4bff34e3Sthurlow NULL, nTotalBytesWritten ); 357*4bff34e3Sthurlow 358*4bff34e3Sthurlow // Adjust Values and sanity check 359*4bff34e3Sthurlow nTotalBytesWritten += nTempLength; 360*4bff34e3Sthurlow nInternalTokenLength -= nTempLength; 361*4bff34e3Sthurlow 362*4bff34e3Sthurlow if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 ) 363*4bff34e3Sthurlow { 364*4bff34e3Sthurlow goto xEndWriteNegTokenInit; 365*4bff34e3Sthurlow } 366*4bff34e3Sthurlow 367*4bff34e3Sthurlow // Neg Init Token Identifier Token 368*4bff34e3Sthurlow nTempLength = ASNDerCalcTokenLength( nTotalBytesWritten, 0L ); 369*4bff34e3Sthurlow 370*4bff34e3Sthurlow // Decrease the pbWriteTokenData, now we know the length and 371*4bff34e3Sthurlow // write it out. 372*4bff34e3Sthurlow pbWriteTokenData -= nTempLength; 373*4bff34e3Sthurlow nTempLength = ASNDerWriteToken( pbWriteTokenData, SPNEGO_NEGINIT_TOKEN_IDENTIFIER, 374*4bff34e3Sthurlow NULL, nTotalBytesWritten ); 375*4bff34e3Sthurlow 376*4bff34e3Sthurlow // Adjust Values and sanity check 377*4bff34e3Sthurlow nTotalBytesWritten += nTempLength; 378*4bff34e3Sthurlow nInternalTokenLength -= nTempLength; 379*4bff34e3Sthurlow 380*4bff34e3Sthurlow if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 ) 381*4bff34e3Sthurlow { 382*4bff34e3Sthurlow goto xEndWriteNegTokenInit; 383*4bff34e3Sthurlow } 384*4bff34e3Sthurlow 385*4bff34e3Sthurlow // SPNEGO OID Token 386*4bff34e3Sthurlow nTempLength = g_stcMechOIDList[spnego_mech_oid_Spnego].iLen; 387*4bff34e3Sthurlow 388*4bff34e3Sthurlow // Decrease the pbWriteTokenData, now we know the length and 389*4bff34e3Sthurlow // write it out. 390*4bff34e3Sthurlow pbWriteTokenData -= nTempLength; 391*4bff34e3Sthurlow nTempLength = ASNDerWriteOID( pbWriteTokenData, spnego_mech_oid_Spnego ); 392*4bff34e3Sthurlow 393*4bff34e3Sthurlow // Adjust Values and sanity check 394*4bff34e3Sthurlow nTotalBytesWritten += nTempLength; 395*4bff34e3Sthurlow nInternalTokenLength -= nTempLength; 396*4bff34e3Sthurlow 397*4bff34e3Sthurlow if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 ) 398*4bff34e3Sthurlow { 399*4bff34e3Sthurlow goto xEndWriteNegTokenInit; 400*4bff34e3Sthurlow } 401*4bff34e3Sthurlow 402*4bff34e3Sthurlow // App Constructed Token 403*4bff34e3Sthurlow nTempLength = ASNDerCalcTokenLength( nTotalBytesWritten, 0L ); 404*4bff34e3Sthurlow 405*4bff34e3Sthurlow // Decrease the pbWriteTokenData, now we know the length and 406*4bff34e3Sthurlow // write it out. 407*4bff34e3Sthurlow pbWriteTokenData -= nTempLength; 408*4bff34e3Sthurlow nTempLength = ASNDerWriteToken( pbWriteTokenData, SPNEGO_NEGINIT_APP_CONSTRUCT, 409*4bff34e3Sthurlow NULL, nTotalBytesWritten ); 410*4bff34e3Sthurlow 411*4bff34e3Sthurlow // Adjust Values and sanity check 412*4bff34e3Sthurlow nTotalBytesWritten += nTempLength; 413*4bff34e3Sthurlow 414*4bff34e3Sthurlow // Don't adjust the internal token length here, it doesn't account 415*4bff34e3Sthurlow // the initial bytes written out (we really don't need to keep 416*4bff34e3Sthurlow // a running count here, but for debugging, it helps to be able 417*4bff34e3Sthurlow // to see the total number of bytes written out as well as the 418*4bff34e3Sthurlow // number of bytes left to write). 419*4bff34e3Sthurlow 420*4bff34e3Sthurlow if ( nTotalBytesWritten == nTokenLength && nInternalTokenLength == 0 && 421*4bff34e3Sthurlow pbWriteTokenData == pbTokenData ) 422*4bff34e3Sthurlow { 423*4bff34e3Sthurlow nReturn = SPNEGO_E_SUCCESS; 424*4bff34e3Sthurlow } 425*4bff34e3Sthurlow 426*4bff34e3Sthurlow xEndWriteNegTokenInit: 427*4bff34e3Sthurlow 428*4bff34e3Sthurlow return nReturn; 429*4bff34e3Sthurlow 430*4bff34e3Sthurlow } 431*4bff34e3Sthurlow 432*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 433*4bff34e3Sthurlow // 434*4bff34e3Sthurlow // Function: 435*4bff34e3Sthurlow // CalculateMinSpnegoTargTokenSize 436*4bff34e3Sthurlow // 437*4bff34e3Sthurlow // Parameters: 438*4bff34e3Sthurlow // [in] MechType - Supported MechType 439*4bff34e3Sthurlow // [in] spnegoNegResult - Neg Result 440*4bff34e3Sthurlow // [in] nMechTokenLength - Length of the MechToken Element 441*4bff34e3Sthurlow // [in] nMechListMICLength - Length of the MechListMIC Element 442*4bff34e3Sthurlow // [out] pnTokenSize - Filled out with total size of token 443*4bff34e3Sthurlow // [out] pnInternalTokenLength - Filled out with length minus length 444*4bff34e3Sthurlow // for initial token. 445*4bff34e3Sthurlow // 446*4bff34e3Sthurlow // Returns: 447*4bff34e3Sthurlow // int Success - SPNEGO_E_SUCCESS 448*4bff34e3Sthurlow // Failure - SPNEGO API Error code 449*4bff34e3Sthurlow // 450*4bff34e3Sthurlow // Comments : 451*4bff34e3Sthurlow // Calculates the required length for a SPNEGO NegTokenTarg token based 452*4bff34e3Sthurlow // on the supplied variable length values and which elements are present. 453*4bff34e3Sthurlow // Note that because the lengths can be represented by an arbitrary 454*4bff34e3Sthurlow // number of bytes in DER encodings, we actually calculate the lengths 455*4bff34e3Sthurlow // backwards, so we always know how many bytes we will potentially be 456*4bff34e3Sthurlow // writing out. 457*4bff34e3Sthurlow // 458*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 459*4bff34e3Sthurlow 460*4bff34e3Sthurlow int CalculateMinSpnegoTargTokenSize( SPNEGO_MECH_OID MechType, 461*4bff34e3Sthurlow SPNEGO_NEGRESULT spnegoNegResult, long nMechTokenLen, 462*4bff34e3Sthurlow long nMechListMICLen, long* pnTokenSize, 463*4bff34e3Sthurlow long* pnInternalTokenLength ) 464*4bff34e3Sthurlow { 465*4bff34e3Sthurlow int nReturn = SPNEGO_E_INVALID_LENGTH; 466*4bff34e3Sthurlow 467*4bff34e3Sthurlow // Start at 0. 468*4bff34e3Sthurlow long nTotalLength = 0; 469*4bff34e3Sthurlow long nTempLength= 0L; 470*4bff34e3Sthurlow 471*4bff34e3Sthurlow // We will calculate this by walking the token backwards 472*4bff34e3Sthurlow 473*4bff34e3Sthurlow // Start with MIC Element 474*4bff34e3Sthurlow if ( nMechListMICLen > 0L ) 475*4bff34e3Sthurlow { 476*4bff34e3Sthurlow nTempLength = ASNDerCalcElementLength( nMechListMICLen, NULL ); 477*4bff34e3Sthurlow 478*4bff34e3Sthurlow // Check for rollover error 479*4bff34e3Sthurlow if ( nTempLength < nMechListMICLen ) 480*4bff34e3Sthurlow { 481*4bff34e3Sthurlow goto xEndTokenTargLength; 482*4bff34e3Sthurlow } 483*4bff34e3Sthurlow 484*4bff34e3Sthurlow nTotalLength += nTempLength; 485*4bff34e3Sthurlow } 486*4bff34e3Sthurlow 487*4bff34e3Sthurlow // Next is the MechToken 488*4bff34e3Sthurlow if ( nMechTokenLen > 0L ) 489*4bff34e3Sthurlow { 490*4bff34e3Sthurlow nTempLength += ASNDerCalcElementLength( nMechTokenLen, NULL ); 491*4bff34e3Sthurlow 492*4bff34e3Sthurlow // Check for rollover error 493*4bff34e3Sthurlow if ( nTempLength < nTotalLength ) 494*4bff34e3Sthurlow { 495*4bff34e3Sthurlow goto xEndTokenTargLength; 496*4bff34e3Sthurlow } 497*4bff34e3Sthurlow 498*4bff34e3Sthurlow nTotalLength = nTempLength; 499*4bff34e3Sthurlow } 500*4bff34e3Sthurlow 501*4bff34e3Sthurlow // Supported MechType 502*4bff34e3Sthurlow if ( spnego_mech_oid_NotUsed != MechType ) 503*4bff34e3Sthurlow { 504*4bff34e3Sthurlow // Supported MechOID element - we use the token function since 505*4bff34e3Sthurlow // we already know the size of the OID token and value 506*4bff34e3Sthurlow nTempLength += ASNDerCalcElementLength( g_stcMechOIDList[MechType].iActualDataLen, 507*4bff34e3Sthurlow NULL ); 508*4bff34e3Sthurlow 509*4bff34e3Sthurlow // Check for rollover error 510*4bff34e3Sthurlow if ( nTempLength < nTotalLength ) 511*4bff34e3Sthurlow { 512*4bff34e3Sthurlow goto xEndTokenTargLength; 513*4bff34e3Sthurlow } 514*4bff34e3Sthurlow 515*4bff34e3Sthurlow nTotalLength = nTempLength; 516*4bff34e3Sthurlow 517*4bff34e3Sthurlow } // IF MechType is available 518*4bff34e3Sthurlow 519*4bff34e3Sthurlow // NegResult Element 520*4bff34e3Sthurlow if ( spnego_negresult_NotUsed != spnegoNegResult ) 521*4bff34e3Sthurlow { 522*4bff34e3Sthurlow nTempLength += ASNDerCalcElementLength( SPNEGO_NEGTARG_MAXLEN_NEGRESULT, NULL ); 523*4bff34e3Sthurlow 524*4bff34e3Sthurlow // Check for rollover error 525*4bff34e3Sthurlow if ( nTempLength < nTotalLength ) 526*4bff34e3Sthurlow { 527*4bff34e3Sthurlow goto xEndTokenTargLength; 528*4bff34e3Sthurlow } 529*4bff34e3Sthurlow 530*4bff34e3Sthurlow nTotalLength = nTempLength; 531*4bff34e3Sthurlow 532*4bff34e3Sthurlow } // IF negResult is available 533*4bff34e3Sthurlow 534*4bff34e3Sthurlow // Following two fields are the basic header tokens 535*4bff34e3Sthurlow 536*4bff34e3Sthurlow // Sequence Token 537*4bff34e3Sthurlow nTempLength += ASNDerCalcTokenLength( nTotalLength, 0L ); 538*4bff34e3Sthurlow 539*4bff34e3Sthurlow // Check for rollover error 540*4bff34e3Sthurlow if ( nTempLength < nTotalLength ) 541*4bff34e3Sthurlow { 542*4bff34e3Sthurlow goto xEndTokenTargLength; 543*4bff34e3Sthurlow } 544*4bff34e3Sthurlow 545*4bff34e3Sthurlow nTotalLength = nTempLength; 546*4bff34e3Sthurlow 547*4bff34e3Sthurlow // Neg Token Identifier Token 548*4bff34e3Sthurlow nTempLength += ASNDerCalcTokenLength( nTotalLength, 0L ); 549*4bff34e3Sthurlow 550*4bff34e3Sthurlow // Check for rollover error 551*4bff34e3Sthurlow if ( nTempLength < nTotalLength ) 552*4bff34e3Sthurlow { 553*4bff34e3Sthurlow goto xEndTokenTargLength; 554*4bff34e3Sthurlow } 555*4bff34e3Sthurlow 556*4bff34e3Sthurlow // The internal length doesn't include the number of bytes 557*4bff34e3Sthurlow // for the initial token 558*4bff34e3Sthurlow *pnInternalTokenLength = nTotalLength; 559*4bff34e3Sthurlow nTotalLength = nTempLength; 560*4bff34e3Sthurlow 561*4bff34e3Sthurlow // We're done 562*4bff34e3Sthurlow *pnTokenSize = nTotalLength; 563*4bff34e3Sthurlow nReturn = SPNEGO_E_SUCCESS; 564*4bff34e3Sthurlow 565*4bff34e3Sthurlow xEndTokenTargLength: 566*4bff34e3Sthurlow 567*4bff34e3Sthurlow return nReturn; 568*4bff34e3Sthurlow 569*4bff34e3Sthurlow } 570*4bff34e3Sthurlow 571*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 572*4bff34e3Sthurlow // 573*4bff34e3Sthurlow // Function: 574*4bff34e3Sthurlow // CreateSpnegoTargToken 575*4bff34e3Sthurlow // 576*4bff34e3Sthurlow // Parameters: 577*4bff34e3Sthurlow // [in] MechType - Supported MechType 578*4bff34e3Sthurlow // [in] eNegResult - NegResult value 579*4bff34e3Sthurlow // [in] pbMechToken - Mech Token Binary Data 580*4bff34e3Sthurlow // [in] ulMechTokenLen - Length of Mech Token 581*4bff34e3Sthurlow // [in] pbMechListMIC - MechListMIC Binary Data 582*4bff34e3Sthurlow // [in] ulMechListMICn - Length of MechListMIC 583*4bff34e3Sthurlow // [out] pbTokenData - Buffer to write token into. 584*4bff34e3Sthurlow // [in] nTokenLength - Length of pbTokenData buffer 585*4bff34e3Sthurlow // [in] nInternalTokenLength - Length of full token without leading 586*4bff34e3Sthurlow // token bytes. 587*4bff34e3Sthurlow // 588*4bff34e3Sthurlow // Returns: 589*4bff34e3Sthurlow // int Success - SPNEGO_E_SUCCESS 590*4bff34e3Sthurlow // Failure - SPNEGO API Error code 591*4bff34e3Sthurlow // 592*4bff34e3Sthurlow // Comments : 593*4bff34e3Sthurlow // Uses DER to fill out pbTokenData with a SPNEGO NegTokenTarg Token 594*4bff34e3Sthurlow // Note that because the lengths can be represented by an arbitrary 595*4bff34e3Sthurlow // number of bytes in DER encodings, we actually calculate the lengths 596*4bff34e3Sthurlow // backwards, so we always know how many bytes we will potentially be 597*4bff34e3Sthurlow // writing out. 598*4bff34e3Sthurlow // 599*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 600*4bff34e3Sthurlow 601*4bff34e3Sthurlow int CreateSpnegoTargToken( SPNEGO_MECH_OID MechType, 602*4bff34e3Sthurlow SPNEGO_NEGRESULT eNegResult, unsigned char* pbMechToken, 603*4bff34e3Sthurlow unsigned long ulMechTokenLen, unsigned char* pbMechListMIC, 604*4bff34e3Sthurlow unsigned long ulMechListMICLen, unsigned char* pbTokenData, 605*4bff34e3Sthurlow long nTokenLength, long nInternalTokenLength ) 606*4bff34e3Sthurlow { 607*4bff34e3Sthurlow int nReturn = SPNEGO_E_INVALID_LENGTH; 608*4bff34e3Sthurlow 609*4bff34e3Sthurlow // Start at 0. 610*4bff34e3Sthurlow long nTempLength= 0L; 611*4bff34e3Sthurlow long nTotalBytesWritten = 0L; 612*4bff34e3Sthurlow long nInternalLength = 0L; 613*4bff34e3Sthurlow 614*4bff34e3Sthurlow unsigned char ucTemp = 0; 615*4bff34e3Sthurlow 616*4bff34e3Sthurlow // We will write the token out backwards to properly handle the cases 617*4bff34e3Sthurlow // where the length bytes become adjustable, so the write location 618*4bff34e3Sthurlow // is initialized to point *just* past the end of the buffer. 619*4bff34e3Sthurlow 620*4bff34e3Sthurlow unsigned char* pbWriteTokenData = pbTokenData + nTokenLength; 621*4bff34e3Sthurlow 622*4bff34e3Sthurlow 623*4bff34e3Sthurlow // Start with MIC Element 624*4bff34e3Sthurlow if ( ulMechListMICLen > 0L ) 625*4bff34e3Sthurlow { 626*4bff34e3Sthurlow nTempLength = ASNDerCalcElementLength( ulMechListMICLen, &nInternalLength ); 627*4bff34e3Sthurlow 628*4bff34e3Sthurlow // Decrease the pbWriteTokenData, now we know the length and 629*4bff34e3Sthurlow // write it out. 630*4bff34e3Sthurlow 631*4bff34e3Sthurlow pbWriteTokenData -= nTempLength; 632*4bff34e3Sthurlow nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGTARG_ELEMENT_MECHLISTMIC, 633*4bff34e3Sthurlow OCTETSTRING, pbMechListMIC, ulMechListMICLen ); 634*4bff34e3Sthurlow 635*4bff34e3Sthurlow // Adjust Values and sanity check 636*4bff34e3Sthurlow nTotalBytesWritten += nTempLength; 637*4bff34e3Sthurlow nInternalTokenLength -= nTempLength; 638*4bff34e3Sthurlow 639*4bff34e3Sthurlow if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 ) 640*4bff34e3Sthurlow { 641*4bff34e3Sthurlow goto xEndWriteNegTokenTarg; 642*4bff34e3Sthurlow } 643*4bff34e3Sthurlow 644*4bff34e3Sthurlow } // IF MechListMIC is present 645*4bff34e3Sthurlow 646*4bff34e3Sthurlow // Next is the MechToken 647*4bff34e3Sthurlow if ( ulMechTokenLen > 0L ) 648*4bff34e3Sthurlow { 649*4bff34e3Sthurlow nTempLength = ASNDerCalcElementLength( ulMechTokenLen, &nInternalLength ); 650*4bff34e3Sthurlow 651*4bff34e3Sthurlow // Decrease the pbWriteTokenData, now we know the length and 652*4bff34e3Sthurlow // write it out. 653*4bff34e3Sthurlow pbWriteTokenData -= nTempLength; 654*4bff34e3Sthurlow nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGTARG_ELEMENT_RESPONSETOKEN, 655*4bff34e3Sthurlow OCTETSTRING, pbMechToken, ulMechTokenLen ); 656*4bff34e3Sthurlow // Adjust Values and sanity check 657*4bff34e3Sthurlow nTotalBytesWritten += nTempLength; 658*4bff34e3Sthurlow nInternalTokenLength -= nTempLength; 659*4bff34e3Sthurlow 660*4bff34e3Sthurlow if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 ) 661*4bff34e3Sthurlow { 662*4bff34e3Sthurlow goto xEndWriteNegTokenTarg; 663*4bff34e3Sthurlow } 664*4bff34e3Sthurlow 665*4bff34e3Sthurlow } // IF MechToken Length is present 666*4bff34e3Sthurlow 667*4bff34e3Sthurlow // Supported Mech Type 668*4bff34e3Sthurlow if ( spnego_mech_oid_NotUsed != MechType ) 669*4bff34e3Sthurlow { 670*4bff34e3Sthurlow 671*4bff34e3Sthurlow nTempLength = ASNDerCalcElementLength( g_stcMechOIDList[MechType].iActualDataLen, 672*4bff34e3Sthurlow &nInternalLength ); 673*4bff34e3Sthurlow 674*4bff34e3Sthurlow // Decrease the pbWriteTokenData, now we know the length and 675*4bff34e3Sthurlow // write it out. 676*4bff34e3Sthurlow pbWriteTokenData -= nTempLength; 677*4bff34e3Sthurlow nTempLength = ASNDerWriteToken( pbWriteTokenData, SPNEGO_NEGTARG_ELEMENT_SUPPORTEDMECH, 678*4bff34e3Sthurlow g_stcMechOIDList[MechType].ucOid, 679*4bff34e3Sthurlow g_stcMechOIDList[MechType].iLen ); 680*4bff34e3Sthurlow 681*4bff34e3Sthurlow // Adjust Values and sanity check 682*4bff34e3Sthurlow nTotalBytesWritten += nTempLength; 683*4bff34e3Sthurlow nInternalTokenLength -= nTempLength; 684*4bff34e3Sthurlow 685*4bff34e3Sthurlow if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 ) 686*4bff34e3Sthurlow { 687*4bff34e3Sthurlow goto xEndWriteNegTokenTarg; 688*4bff34e3Sthurlow } 689*4bff34e3Sthurlow 690*4bff34e3Sthurlow } // IF MechType is present 691*4bff34e3Sthurlow 692*4bff34e3Sthurlow // Neg Result 693*4bff34e3Sthurlow // NegResult Element 694*4bff34e3Sthurlow if ( spnego_negresult_NotUsed != eNegResult ) 695*4bff34e3Sthurlow { 696*4bff34e3Sthurlow ucTemp = (unsigned char) eNegResult; 697*4bff34e3Sthurlow 698*4bff34e3Sthurlow nTempLength = ASNDerCalcElementLength( SPNEGO_NEGTARG_MAXLEN_NEGRESULT, &nInternalLength ); 699*4bff34e3Sthurlow 700*4bff34e3Sthurlow // Decrease the pbWriteTokenData, now we know the length and 701*4bff34e3Sthurlow // write it out. 702*4bff34e3Sthurlow pbWriteTokenData -= nTempLength; 703*4bff34e3Sthurlow nTempLength = ASNDerWriteElement( pbWriteTokenData, SPNEGO_NEGTARG_ELEMENT_NEGRESULT, 704*4bff34e3Sthurlow ENUMERATED, &ucTemp, SPNEGO_NEGTARG_MAXLEN_NEGRESULT ); 705*4bff34e3Sthurlow 706*4bff34e3Sthurlow // Adjust Values and sanity check 707*4bff34e3Sthurlow nTotalBytesWritten += nTempLength; 708*4bff34e3Sthurlow nInternalTokenLength -= nTempLength; 709*4bff34e3Sthurlow 710*4bff34e3Sthurlow if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 ) 711*4bff34e3Sthurlow { 712*4bff34e3Sthurlow goto xEndWriteNegTokenTarg; 713*4bff34e3Sthurlow } 714*4bff34e3Sthurlow 715*4bff34e3Sthurlow } // If eNegResult is available 716*4bff34e3Sthurlow 717*4bff34e3Sthurlow // The next tokens we're writing out reflect the total number of bytes 718*4bff34e3Sthurlow // we have actually written out. 719*4bff34e3Sthurlow 720*4bff34e3Sthurlow // Sequence Token 721*4bff34e3Sthurlow nTempLength = ASNDerCalcTokenLength( nTotalBytesWritten, 0L ); 722*4bff34e3Sthurlow 723*4bff34e3Sthurlow // Decrease the pbWriteTokenData, now we know the length and 724*4bff34e3Sthurlow // write it out. 725*4bff34e3Sthurlow pbWriteTokenData -= nTempLength; 726*4bff34e3Sthurlow nTempLength = ASNDerWriteToken( pbWriteTokenData, SPNEGO_CONSTRUCTED_SEQUENCE, 727*4bff34e3Sthurlow NULL, nTotalBytesWritten ); 728*4bff34e3Sthurlow 729*4bff34e3Sthurlow // Adjust Values and sanity check 730*4bff34e3Sthurlow nTotalBytesWritten += nTempLength; 731*4bff34e3Sthurlow nInternalTokenLength -= nTempLength; 732*4bff34e3Sthurlow 733*4bff34e3Sthurlow if ( nTotalBytesWritten > nTokenLength || nInternalTokenLength < 0 ) 734*4bff34e3Sthurlow { 735*4bff34e3Sthurlow goto xEndWriteNegTokenTarg; 736*4bff34e3Sthurlow } 737*4bff34e3Sthurlow 738*4bff34e3Sthurlow // Neg Targ Token Identifier Token 739*4bff34e3Sthurlow nTempLength = ASNDerCalcTokenLength( nTotalBytesWritten, 0L ); 740*4bff34e3Sthurlow 741*4bff34e3Sthurlow // Decrease the pbWriteTokenData, now we know the length and 742*4bff34e3Sthurlow // write it out. 743*4bff34e3Sthurlow pbWriteTokenData -= nTempLength; 744*4bff34e3Sthurlow nTempLength = ASNDerWriteToken( pbWriteTokenData, SPNEGO_NEGTARG_TOKEN_IDENTIFIER, 745*4bff34e3Sthurlow NULL, nTotalBytesWritten ); 746*4bff34e3Sthurlow 747*4bff34e3Sthurlow // Adjust Values and sanity check 748*4bff34e3Sthurlow nTotalBytesWritten += nTempLength; 749*4bff34e3Sthurlow 750*4bff34e3Sthurlow // Don't adjust the internal token length here, it doesn't account 751*4bff34e3Sthurlow // the initial bytes written out (we really don't need to keep 752*4bff34e3Sthurlow // a running count here, but for debugging, it helps to be able 753*4bff34e3Sthurlow // to see the total number of bytes written out as well as the 754*4bff34e3Sthurlow // number of bytes left to write). 755*4bff34e3Sthurlow 756*4bff34e3Sthurlow if ( nTotalBytesWritten == nTokenLength && nInternalTokenLength == 0 && 757*4bff34e3Sthurlow pbWriteTokenData == pbTokenData ) 758*4bff34e3Sthurlow { 759*4bff34e3Sthurlow nReturn = SPNEGO_E_SUCCESS; 760*4bff34e3Sthurlow } 761*4bff34e3Sthurlow 762*4bff34e3Sthurlow 763*4bff34e3Sthurlow xEndWriteNegTokenTarg: 764*4bff34e3Sthurlow 765*4bff34e3Sthurlow return nReturn; 766*4bff34e3Sthurlow 767*4bff34e3Sthurlow 768*4bff34e3Sthurlow } 769*4bff34e3Sthurlow 770*4bff34e3Sthurlow 771*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 772*4bff34e3Sthurlow // 773*4bff34e3Sthurlow // Function: 774*4bff34e3Sthurlow // AllocEmptySpnegoToken 775*4bff34e3Sthurlow // 776*4bff34e3Sthurlow // Parameters: 777*4bff34e3Sthurlow // [in] ucCopyData - Flag to copy data or pointer. 778*4bff34e3Sthurlow // [in] ulFlags - Flags for SPNEGO_TOKEN data member. 779*4bff34e3Sthurlow // [in] pbTokenData - Binary token data. 780*4bff34e3Sthurlow // [in] ulTokenSize - Size of pbTokenData. 781*4bff34e3Sthurlow // 782*4bff34e3Sthurlow // Returns: 783*4bff34e3Sthurlow // SPNEGO_TOKEN* Success - Pointer to initialized SPNEGO_TOKEN struct 784*4bff34e3Sthurlow // Failure - NULL 785*4bff34e3Sthurlow // 786*4bff34e3Sthurlow // Comments : 787*4bff34e3Sthurlow // Allocates a SPNEGO_TOKEN data structure and initializes it. Based on 788*4bff34e3Sthurlow // the value of ucCopyData, if non-zero, we copy the data into a buffer 789*4bff34e3Sthurlow // we allocate in this function, otherwise, we copy the data pointer 790*4bff34e3Sthurlow // direcly. 791*4bff34e3Sthurlow // 792*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 793*4bff34e3Sthurlow 794*4bff34e3Sthurlow SPNEGO_TOKEN* AllocEmptySpnegoToken( unsigned char ucCopyData, unsigned long ulFlags, 795*4bff34e3Sthurlow unsigned char * pbTokenData, unsigned long ulTokenSize ) 796*4bff34e3Sthurlow { 797*4bff34e3Sthurlow SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) calloc( 1, sizeof(SPNEGO_TOKEN) ); 798*4bff34e3Sthurlow 799*4bff34e3Sthurlow if ( NULL != pSpnegoToken ) 800*4bff34e3Sthurlow { 801*4bff34e3Sthurlow // Set the token size 802*4bff34e3Sthurlow pSpnegoToken->nStructSize = SPNEGO_TOKEN_SIZE; 803*4bff34e3Sthurlow 804*4bff34e3Sthurlow // Initialize the element array 805*4bff34e3Sthurlow InitSpnegoTokenElementArray( pSpnegoToken ); 806*4bff34e3Sthurlow 807*4bff34e3Sthurlow // Assign the flags value 808*4bff34e3Sthurlow pSpnegoToken->ulFlags = ulFlags; 809*4bff34e3Sthurlow 810*4bff34e3Sthurlow // 811*4bff34e3Sthurlow // IF ucCopyData is TRUE, we will allocate a buffer and copy data into it. 812*4bff34e3Sthurlow // Otherwise, we will just copy the pointer and the length. This is so we 813*4bff34e3Sthurlow // can cut out additional allocations for performance reasons 814*4bff34e3Sthurlow // 815*4bff34e3Sthurlow 816*4bff34e3Sthurlow if ( SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA == ucCopyData ) 817*4bff34e3Sthurlow { 818*4bff34e3Sthurlow // Alloc the internal buffer. Cleanup on failure. 819*4bff34e3Sthurlow pSpnegoToken->pbBinaryData = (unsigned char*) calloc( ulTokenSize, sizeof(unsigned char) ); 820*4bff34e3Sthurlow 821*4bff34e3Sthurlow if ( NULL != pSpnegoToken->pbBinaryData ) 822*4bff34e3Sthurlow { 823*4bff34e3Sthurlow // We must ALWAYS free this buffer 824*4bff34e3Sthurlow pSpnegoToken->ulFlags |= SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA; 825*4bff34e3Sthurlow 826*4bff34e3Sthurlow // Copy the data locally 827*4bff34e3Sthurlow memcpy( pSpnegoToken->pbBinaryData, pbTokenData, ulTokenSize ); 828*4bff34e3Sthurlow pSpnegoToken->ulBinaryDataLen = ulTokenSize; 829*4bff34e3Sthurlow } 830*4bff34e3Sthurlow else 831*4bff34e3Sthurlow { 832*4bff34e3Sthurlow free( pSpnegoToken ); 833*4bff34e3Sthurlow pSpnegoToken = NULL; 834*4bff34e3Sthurlow } 835*4bff34e3Sthurlow 836*4bff34e3Sthurlow } // IF ucCopyData 837*4bff34e3Sthurlow else 838*4bff34e3Sthurlow { 839*4bff34e3Sthurlow // Copy the pointer and the length directly - ulFlags will control whether or not 840*4bff34e3Sthurlow // we are allowed to free the value 841*4bff34e3Sthurlow 842*4bff34e3Sthurlow pSpnegoToken->pbBinaryData = pbTokenData; 843*4bff34e3Sthurlow pSpnegoToken->ulBinaryDataLen = ulTokenSize; 844*4bff34e3Sthurlow } 845*4bff34e3Sthurlow 846*4bff34e3Sthurlow } 847*4bff34e3Sthurlow 848*4bff34e3Sthurlow return pSpnegoToken; 849*4bff34e3Sthurlow } 850*4bff34e3Sthurlow 851*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 852*4bff34e3Sthurlow // 853*4bff34e3Sthurlow // Function: 854*4bff34e3Sthurlow // FreeSpnegoToken 855*4bff34e3Sthurlow // 856*4bff34e3Sthurlow // Parameters: 857*4bff34e3Sthurlow // [in] pSpnegoToken - Points to SPNEGO_TOKEN to free. 858*4bff34e3Sthurlow // 859*4bff34e3Sthurlow // Returns: 860*4bff34e3Sthurlow // void 861*4bff34e3Sthurlow // 862*4bff34e3Sthurlow // Comments : 863*4bff34e3Sthurlow // If non-NULL, interprets pSpnegoToken, freeing any internal allocations 864*4bff34e3Sthurlow // and finally the actual structure. 865*4bff34e3Sthurlow // 866*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 867*4bff34e3Sthurlow 868*4bff34e3Sthurlow void FreeSpnegoToken( SPNEGO_TOKEN* pSpnegoToken ) 869*4bff34e3Sthurlow { 870*4bff34e3Sthurlow if ( NULL != pSpnegoToken ) 871*4bff34e3Sthurlow { 872*4bff34e3Sthurlow 873*4bff34e3Sthurlow // Cleanup internal allocation per the flags 874*4bff34e3Sthurlow if ( pSpnegoToken->ulFlags & SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA && 875*4bff34e3Sthurlow NULL != pSpnegoToken->pbBinaryData ) 876*4bff34e3Sthurlow { 877*4bff34e3Sthurlow free( pSpnegoToken->pbBinaryData ); 878*4bff34e3Sthurlow pSpnegoToken->pbBinaryData = NULL; 879*4bff34e3Sthurlow } 880*4bff34e3Sthurlow 881*4bff34e3Sthurlow free ( pSpnegoToken ); 882*4bff34e3Sthurlow } 883*4bff34e3Sthurlow } 884*4bff34e3Sthurlow 885*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 886*4bff34e3Sthurlow // 887*4bff34e3Sthurlow // Function: 888*4bff34e3Sthurlow // InitSpnegoTokenElementArray 889*4bff34e3Sthurlow // 890*4bff34e3Sthurlow // Parameters: 891*4bff34e3Sthurlow // [in] pSpnegoToken - Points to SPNEGO_TOKEN structure. 892*4bff34e3Sthurlow // 893*4bff34e3Sthurlow // Returns: 894*4bff34e3Sthurlow // void 895*4bff34e3Sthurlow // 896*4bff34e3Sthurlow // Comments : 897*4bff34e3Sthurlow // Initializes the element array data member of a SPNEGO_TOKEN data 898*4bff34e3Sthurlow // structure. 899*4bff34e3Sthurlow // 900*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 901*4bff34e3Sthurlow 902*4bff34e3Sthurlow void InitSpnegoTokenElementArray( SPNEGO_TOKEN* pSpnegoToken ) 903*4bff34e3Sthurlow { 904*4bff34e3Sthurlow int nCtr; 905*4bff34e3Sthurlow 906*4bff34e3Sthurlow // Set the number of elemnts 907*4bff34e3Sthurlow pSpnegoToken->nNumElements = MAX_NUM_TOKEN_ELEMENTS; 908*4bff34e3Sthurlow 909*4bff34e3Sthurlow // 910*4bff34e3Sthurlow // Initially, all elements are unavailable 911*4bff34e3Sthurlow // 912*4bff34e3Sthurlow 913*4bff34e3Sthurlow for ( nCtr = 0; nCtr < MAX_NUM_TOKEN_ELEMENTS; nCtr++ ) 914*4bff34e3Sthurlow { 915*4bff34e3Sthurlow // Set the element size as well 916*4bff34e3Sthurlow pSpnegoToken->aElementArray[ nCtr ].nStructSize = SPNEGO_ELEMENT_SIZE; 917*4bff34e3Sthurlow pSpnegoToken->aElementArray[ nCtr ].iElementPresent = SPNEGO_TOKEN_ELEMENT_UNAVAILABLE; 918*4bff34e3Sthurlow } 919*4bff34e3Sthurlow 920*4bff34e3Sthurlow } 921*4bff34e3Sthurlow 922*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 923*4bff34e3Sthurlow // 924*4bff34e3Sthurlow // Function: 925*4bff34e3Sthurlow // InitSpnegoTokenType 926*4bff34e3Sthurlow // 927*4bff34e3Sthurlow // Parameters: 928*4bff34e3Sthurlow // [in] pSpnegoToken - Points to SPNEGO_TOKEN structure. 929*4bff34e3Sthurlow // [out] pnTokenLength - Filled out with total token length 930*4bff34e3Sthurlow // [out] pnRemainingTokenLength - Filled out with remaining length 931*4bff34e3Sthurlow // after header is parsed 932*4bff34e3Sthurlow // [out] ppbFirstElement - Filled out with pointer to first 933*4bff34e3Sthurlow // element after header info. 934*4bff34e3Sthurlow // 935*4bff34e3Sthurlow // Returns: 936*4bff34e3Sthurlow // int Success - SPNEGO_E_SUCCESS 937*4bff34e3Sthurlow // Failure - SPNEGO API Error code 938*4bff34e3Sthurlow // 939*4bff34e3Sthurlow // Comments : 940*4bff34e3Sthurlow // Walks the underlying binary data for a SPNEGO_TOKEN data structure 941*4bff34e3Sthurlow // and determines the type of the underlying token based on token header 942*4bff34e3Sthurlow // information. 943*4bff34e3Sthurlow // 944*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 945*4bff34e3Sthurlow 946*4bff34e3Sthurlow int InitSpnegoTokenType( SPNEGO_TOKEN* pSpnegoToken, long* pnTokenLength, 947*4bff34e3Sthurlow long* pnRemainingTokenLength, unsigned char** ppbFirstElement ) 948*4bff34e3Sthurlow { 949*4bff34e3Sthurlow int nReturn = SPNEGO_E_INVALID_TOKEN; 950*4bff34e3Sthurlow long nActualTokenLength = 0L; 951*4bff34e3Sthurlow long nBoundaryLength = pSpnegoToken->ulBinaryDataLen; 952*4bff34e3Sthurlow unsigned char* pbTokenData = pSpnegoToken->pbBinaryData; 953*4bff34e3Sthurlow 954*4bff34e3Sthurlow // 955*4bff34e3Sthurlow // First byte MUST be either an APP_CONSTRUCT or the NEGTARG_TOKEN_TARG 956*4bff34e3Sthurlow // 957*4bff34e3Sthurlow 958*4bff34e3Sthurlow if ( SPNEGO_NEGINIT_APP_CONSTRUCT == *pbTokenData ) 959*4bff34e3Sthurlow { 960*4bff34e3Sthurlow // Validate the above token - this will tell us the actual length of the token 961*4bff34e3Sthurlow // per the encoding (minus the actual token bytes) 962*4bff34e3Sthurlow if ( ( nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_NEGINIT_APP_CONSTRUCT, 0L, nBoundaryLength, 963*4bff34e3Sthurlow pnTokenLength, &nActualTokenLength ) ) 964*4bff34e3Sthurlow == SPNEGO_E_SUCCESS ) 965*4bff34e3Sthurlow { 966*4bff34e3Sthurlow // Initialize the remaining token length value. This will be used 967*4bff34e3Sthurlow // to tell the caller how much token there is left once we've parsed 968*4bff34e3Sthurlow // the header (they could calculate it from the other values, but this 969*4bff34e3Sthurlow // is a bit friendlier) 970*4bff34e3Sthurlow *pnRemainingTokenLength = *pnTokenLength; 971*4bff34e3Sthurlow 972*4bff34e3Sthurlow // Make adjustments to next token 973*4bff34e3Sthurlow pbTokenData += nActualTokenLength; 974*4bff34e3Sthurlow nBoundaryLength -= nActualTokenLength; 975*4bff34e3Sthurlow 976*4bff34e3Sthurlow // The next token should be an OID 977*4bff34e3Sthurlow if ( ( nReturn = ASNDerCheckOID( pbTokenData, spnego_mech_oid_Spnego, nBoundaryLength, 978*4bff34e3Sthurlow &nActualTokenLength ) ) == SPNEGO_E_SUCCESS ) 979*4bff34e3Sthurlow { 980*4bff34e3Sthurlow // Make adjustments to next token 981*4bff34e3Sthurlow pbTokenData += nActualTokenLength; 982*4bff34e3Sthurlow nBoundaryLength -= nActualTokenLength; 983*4bff34e3Sthurlow *pnRemainingTokenLength -= nActualTokenLength; 984*4bff34e3Sthurlow 985*4bff34e3Sthurlow // The next token should specify the NegTokenInit 986*4bff34e3Sthurlow if ( ( nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_NEGINIT_TOKEN_IDENTIFIER, 987*4bff34e3Sthurlow *pnRemainingTokenLength, nBoundaryLength, pnTokenLength, 988*4bff34e3Sthurlow &nActualTokenLength ) ) 989*4bff34e3Sthurlow == SPNEGO_E_SUCCESS ) 990*4bff34e3Sthurlow { 991*4bff34e3Sthurlow // Make adjustments to next token 992*4bff34e3Sthurlow pbTokenData += nActualTokenLength; 993*4bff34e3Sthurlow nBoundaryLength -= nActualTokenLength; 994*4bff34e3Sthurlow *pnRemainingTokenLength -= nActualTokenLength; 995*4bff34e3Sthurlow 996*4bff34e3Sthurlow // The next token should specify the start of a sequence 997*4bff34e3Sthurlow if ( ( nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_CONSTRUCTED_SEQUENCE, 998*4bff34e3Sthurlow *pnRemainingTokenLength, nBoundaryLength, pnTokenLength, 999*4bff34e3Sthurlow &nActualTokenLength ) ) 1000*4bff34e3Sthurlow == SPNEGO_E_SUCCESS ) 1001*4bff34e3Sthurlow { 1002*4bff34e3Sthurlow // NegTokenInit header is now checked out! 1003*4bff34e3Sthurlow 1004*4bff34e3Sthurlow // Make adjustments to next token 1005*4bff34e3Sthurlow *pnRemainingTokenLength -= nActualTokenLength; 1006*4bff34e3Sthurlow 1007*4bff34e3Sthurlow // Store pointer to first element 1008*4bff34e3Sthurlow *ppbFirstElement = pbTokenData + nActualTokenLength; 1009*4bff34e3Sthurlow pSpnegoToken->ucTokenType = SPNEGO_TOKEN_INIT; 1010*4bff34e3Sthurlow } // IF Check Sequence Token 1011*4bff34e3Sthurlow 1012*4bff34e3Sthurlow } // IF Check NegTokenInit token 1013*4bff34e3Sthurlow 1014*4bff34e3Sthurlow 1015*4bff34e3Sthurlow } // IF Check for SPNEGO OID 1016*4bff34e3Sthurlow 1017*4bff34e3Sthurlow 1018*4bff34e3Sthurlow } // IF check app construct token 1019*4bff34e3Sthurlow 1020*4bff34e3Sthurlow } 1021*4bff34e3Sthurlow else if ( SPNEGO_NEGTARG_TOKEN_IDENTIFIER == *pbTokenData ) 1022*4bff34e3Sthurlow { 1023*4bff34e3Sthurlow 1024*4bff34e3Sthurlow // The next token should specify the NegTokenInit 1025*4bff34e3Sthurlow if ( ( nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_NEGTARG_TOKEN_IDENTIFIER, 1026*4bff34e3Sthurlow *pnRemainingTokenLength, nBoundaryLength, pnTokenLength, 1027*4bff34e3Sthurlow &nActualTokenLength ) ) 1028*4bff34e3Sthurlow == SPNEGO_E_SUCCESS ) 1029*4bff34e3Sthurlow { 1030*4bff34e3Sthurlow // Initialize the remaining token length value. This will be used 1031*4bff34e3Sthurlow // to tell the caller how much token there is left once we've parsed 1032*4bff34e3Sthurlow // the header (they could calculate it from the other values, but this 1033*4bff34e3Sthurlow // is a bit friendlier) 1034*4bff34e3Sthurlow *pnRemainingTokenLength = *pnTokenLength; 1035*4bff34e3Sthurlow 1036*4bff34e3Sthurlow // Make adjustments to next token 1037*4bff34e3Sthurlow pbTokenData += nActualTokenLength; 1038*4bff34e3Sthurlow nBoundaryLength -= nActualTokenLength; 1039*4bff34e3Sthurlow 1040*4bff34e3Sthurlow // The next token should specify the start of a sequence 1041*4bff34e3Sthurlow if ( ( nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_CONSTRUCTED_SEQUENCE, 1042*4bff34e3Sthurlow *pnRemainingTokenLength, nBoundaryLength, pnTokenLength, 1043*4bff34e3Sthurlow &nActualTokenLength ) ) 1044*4bff34e3Sthurlow == SPNEGO_E_SUCCESS ) 1045*4bff34e3Sthurlow { 1046*4bff34e3Sthurlow // NegTokenInit header is now checked out! 1047*4bff34e3Sthurlow 1048*4bff34e3Sthurlow // Make adjustments to next token 1049*4bff34e3Sthurlow *pnRemainingTokenLength -= nActualTokenLength; 1050*4bff34e3Sthurlow 1051*4bff34e3Sthurlow // Store pointer to first element 1052*4bff34e3Sthurlow *ppbFirstElement = pbTokenData + nActualTokenLength; 1053*4bff34e3Sthurlow pSpnegoToken->ucTokenType = SPNEGO_TOKEN_TARG; 1054*4bff34e3Sthurlow } // IF Check Sequence Token 1055*4bff34e3Sthurlow 1056*4bff34e3Sthurlow } // IF Check NegTokenInit token 1057*4bff34e3Sthurlow 1058*4bff34e3Sthurlow } // ELSE IF it's a NegTokenTarg 1059*4bff34e3Sthurlow 1060*4bff34e3Sthurlow return nReturn; 1061*4bff34e3Sthurlow } 1062*4bff34e3Sthurlow 1063*4bff34e3Sthurlow 1064*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 1065*4bff34e3Sthurlow // 1066*4bff34e3Sthurlow // Function: 1067*4bff34e3Sthurlow // GetSpnegoInitTokenMechList 1068*4bff34e3Sthurlow // 1069*4bff34e3Sthurlow // Parameters: 1070*4bff34e3Sthurlow // [in] pbTokenData - Points to binary MechList element 1071*4bff34e3Sthurlow // in NegTokenInit. 1072*4bff34e3Sthurlow // [in] nMechListLength - Length of the MechList 1073*4bff34e3Sthurlow // [out] pSpnegoElement - Filled out with MechList Element 1074*4bff34e3Sthurlow // data. 1075*4bff34e3Sthurlow // 1076*4bff34e3Sthurlow // Returns: 1077*4bff34e3Sthurlow // int Success - SPNEGO_E_SUCCESS 1078*4bff34e3Sthurlow // Failure - SPNEGO API Error code 1079*4bff34e3Sthurlow // 1080*4bff34e3Sthurlow // Comments : 1081*4bff34e3Sthurlow // Checks that pbTokenData is pointing at something that at least 1082*4bff34e3Sthurlow // *looks* like a MechList and then fills out the supplied 1083*4bff34e3Sthurlow // SPNEGO_ELEMENT structure. 1084*4bff34e3Sthurlow // 1085*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 1086*4bff34e3Sthurlow 1087*4bff34e3Sthurlow int GetSpnegoInitTokenMechList( unsigned char* pbTokenData, int nMechListLength, 1088*4bff34e3Sthurlow SPNEGO_ELEMENT* pSpnegoElement ) 1089*4bff34e3Sthurlow { 1090*4bff34e3Sthurlow int nReturn = SPNEGO_E_INVALID_TOKEN; 1091*4bff34e3Sthurlow long nLength = 0L; 1092*4bff34e3Sthurlow long nActualTokenLength = 0L; 1093*4bff34e3Sthurlow 1094*4bff34e3Sthurlow // Actual MechList is prepended by a Constructed Sequence Token 1095*4bff34e3Sthurlow if ( ( nReturn = ASNDerCheckToken( pbTokenData, SPNEGO_CONSTRUCTED_SEQUENCE, 1096*4bff34e3Sthurlow nMechListLength, nMechListLength, 1097*4bff34e3Sthurlow &nLength, &nActualTokenLength ) ) 1098*4bff34e3Sthurlow == SPNEGO_E_SUCCESS ) 1099*4bff34e3Sthurlow { 1100*4bff34e3Sthurlow // Adjust for this token 1101*4bff34e3Sthurlow nMechListLength -= nActualTokenLength; 1102*4bff34e3Sthurlow pbTokenData += nActualTokenLength; 1103*4bff34e3Sthurlow 1104*4bff34e3Sthurlow // Perform simple validation of the actual MechList (i.e. ensure that 1105*4bff34e3Sthurlow // the OIDs in the MechList are reasonable). 1106*4bff34e3Sthurlow 1107*4bff34e3Sthurlow if ( ( nReturn = ValidateMechList( pbTokenData, nLength ) ) == SPNEGO_E_SUCCESS ) 1108*4bff34e3Sthurlow { 1109*4bff34e3Sthurlow // Initialize the element now 1110*4bff34e3Sthurlow pSpnegoElement->eElementType = spnego_init_mechtypes; 1111*4bff34e3Sthurlow pSpnegoElement->iElementPresent = SPNEGO_TOKEN_ELEMENT_AVAILABLE; 1112*4bff34e3Sthurlow pSpnegoElement->type = SPNEGO_MECHLIST_TYPE; 1113*4bff34e3Sthurlow pSpnegoElement->nDatalength = nLength; 1114*4bff34e3Sthurlow pSpnegoElement->pbData = pbTokenData; 1115*4bff34e3Sthurlow } 1116*4bff34e3Sthurlow 1117*4bff34e3Sthurlow } // IF Check Token 1118*4bff34e3Sthurlow 1119*4bff34e3Sthurlow return nReturn; 1120*4bff34e3Sthurlow } 1121*4bff34e3Sthurlow 1122*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 1123*4bff34e3Sthurlow // 1124*4bff34e3Sthurlow // Function: 1125*4bff34e3Sthurlow // InitSpnegoTokenElementFromBasicType 1126*4bff34e3Sthurlow // 1127*4bff34e3Sthurlow // Parameters: 1128*4bff34e3Sthurlow // [in] pbTokenData - Points to binary element data in 1129*4bff34e3Sthurlow // a SPNEGO token. 1130*4bff34e3Sthurlow // [in] nElementLength - Length of the element 1131*4bff34e3Sthurlow // [in] ucExpectedType - Expected DER type. 1132*4bff34e3Sthurlow // [in] spnegoElementType - Which element is this? 1133*4bff34e3Sthurlow // [out] pSpnegoElement - Filled out with element data. 1134*4bff34e3Sthurlow // 1135*4bff34e3Sthurlow // Returns: 1136*4bff34e3Sthurlow // int Success - SPNEGO_E_SUCCESS 1137*4bff34e3Sthurlow // Failure - SPNEGO API Error code 1138*4bff34e3Sthurlow // 1139*4bff34e3Sthurlow // Comments : 1140*4bff34e3Sthurlow // Checks that pbTokenData is pointing at the specified DER type. If so, 1141*4bff34e3Sthurlow // then we verify that lengths are proper and then fill out the 1142*4bff34e3Sthurlow // SPNEGO_ELEMENT data structure. 1143*4bff34e3Sthurlow // 1144*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 1145*4bff34e3Sthurlow 1146*4bff34e3Sthurlow int InitSpnegoTokenElementFromBasicType( unsigned char* pbTokenData, int nElementLength, 1147*4bff34e3Sthurlow unsigned char ucExpectedType, 1148*4bff34e3Sthurlow SPNEGO_ELEMENT_TYPE spnegoElementType, 1149*4bff34e3Sthurlow SPNEGO_ELEMENT* pSpnegoElement ) 1150*4bff34e3Sthurlow { 1151*4bff34e3Sthurlow int nReturn = SPNEGO_E_UNEXPECTED_TYPE; 1152*4bff34e3Sthurlow long nLength = 0L; 1153*4bff34e3Sthurlow long nActualTokenLength = 0L; 1154*4bff34e3Sthurlow 1155*4bff34e3Sthurlow // The type BYTE must match our token data or something is badly wrong 1156*4bff34e3Sthurlow if ( *pbTokenData == ucExpectedType ) 1157*4bff34e3Sthurlow { 1158*4bff34e3Sthurlow 1159*4bff34e3Sthurlow // Check that we are pointing at the specified type 1160*4bff34e3Sthurlow if ( ( nReturn = ASNDerCheckToken( pbTokenData, ucExpectedType, 1161*4bff34e3Sthurlow nElementLength, nElementLength, 1162*4bff34e3Sthurlow &nLength, &nActualTokenLength ) ) 1163*4bff34e3Sthurlow == SPNEGO_E_SUCCESS ) 1164*4bff34e3Sthurlow { 1165*4bff34e3Sthurlow // Adjust for this token 1166*4bff34e3Sthurlow nElementLength -= nActualTokenLength; 1167*4bff34e3Sthurlow pbTokenData += nActualTokenLength; 1168*4bff34e3Sthurlow 1169*4bff34e3Sthurlow // Initialize the element now 1170*4bff34e3Sthurlow pSpnegoElement->eElementType = spnegoElementType; 1171*4bff34e3Sthurlow pSpnegoElement->iElementPresent = SPNEGO_TOKEN_ELEMENT_AVAILABLE; 1172*4bff34e3Sthurlow pSpnegoElement->type = ucExpectedType; 1173*4bff34e3Sthurlow pSpnegoElement->nDatalength = nLength; 1174*4bff34e3Sthurlow pSpnegoElement->pbData = pbTokenData; 1175*4bff34e3Sthurlow } 1176*4bff34e3Sthurlow 1177*4bff34e3Sthurlow } // IF type makes sense 1178*4bff34e3Sthurlow 1179*4bff34e3Sthurlow return nReturn; 1180*4bff34e3Sthurlow } 1181*4bff34e3Sthurlow 1182*4bff34e3Sthurlow 1183*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 1184*4bff34e3Sthurlow // 1185*4bff34e3Sthurlow // Function: 1186*4bff34e3Sthurlow // InitSpnegoTokenElementFromOID 1187*4bff34e3Sthurlow // 1188*4bff34e3Sthurlow // Parameters: 1189*4bff34e3Sthurlow // [in] pbTokenData - Points to binary element data in 1190*4bff34e3Sthurlow // a SPNEGO token. 1191*4bff34e3Sthurlow // [in] nElementLength - Length of the element 1192*4bff34e3Sthurlow // [in] spnegoElementType - Which element is this? 1193*4bff34e3Sthurlow // [out] pSpnegoElement - Filled out with element data. 1194*4bff34e3Sthurlow // 1195*4bff34e3Sthurlow // Returns: 1196*4bff34e3Sthurlow // int Success - SPNEGO_E_SUCCESS 1197*4bff34e3Sthurlow // Failure - SPNEGO API Error code 1198*4bff34e3Sthurlow // 1199*4bff34e3Sthurlow // Comments : 1200*4bff34e3Sthurlow // Initializes a SpnegoElement from an OID - normally, this would have 1201*4bff34e3Sthurlow // used the Basic Type function above, but since we do binary compares 1202*4bff34e3Sthurlow // on the OIDs against the DER information as well as the OID, we need 1203*4bff34e3Sthurlow // to account for that. 1204*4bff34e3Sthurlow // 1205*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 1206*4bff34e3Sthurlow 1207*4bff34e3Sthurlow int InitSpnegoTokenElementFromOID( unsigned char* pbTokenData, int nElementLength, 1208*4bff34e3Sthurlow SPNEGO_ELEMENT_TYPE spnegoElementType, 1209*4bff34e3Sthurlow SPNEGO_ELEMENT* pSpnegoElement ) 1210*4bff34e3Sthurlow { 1211*4bff34e3Sthurlow int nReturn = SPNEGO_E_UNEXPECTED_TYPE; 1212*4bff34e3Sthurlow long nLength = 0L; 1213*4bff34e3Sthurlow long nActualTokenLength = 0L; 1214*4bff34e3Sthurlow 1215*4bff34e3Sthurlow // The type BYTE must match our token data or something is badly wrong 1216*4bff34e3Sthurlow if ( *pbTokenData == OID ) 1217*4bff34e3Sthurlow { 1218*4bff34e3Sthurlow 1219*4bff34e3Sthurlow // Check that we are pointing at an OID type 1220*4bff34e3Sthurlow if ( ( nReturn = ASNDerCheckToken( pbTokenData, OID, 1221*4bff34e3Sthurlow nElementLength, nElementLength, 1222*4bff34e3Sthurlow &nLength, &nActualTokenLength ) ) 1223*4bff34e3Sthurlow == SPNEGO_E_SUCCESS ) 1224*4bff34e3Sthurlow { 1225*4bff34e3Sthurlow // Don't adjust any values for this function 1226*4bff34e3Sthurlow 1227*4bff34e3Sthurlow // Initialize the element now 1228*4bff34e3Sthurlow pSpnegoElement->eElementType = spnegoElementType; 1229*4bff34e3Sthurlow pSpnegoElement->iElementPresent = SPNEGO_TOKEN_ELEMENT_AVAILABLE; 1230*4bff34e3Sthurlow pSpnegoElement->type = OID; 1231*4bff34e3Sthurlow pSpnegoElement->nDatalength = nElementLength; 1232*4bff34e3Sthurlow pSpnegoElement->pbData = pbTokenData; 1233*4bff34e3Sthurlow } 1234*4bff34e3Sthurlow 1235*4bff34e3Sthurlow } // IF type makes sense 1236*4bff34e3Sthurlow 1237*4bff34e3Sthurlow return nReturn; 1238*4bff34e3Sthurlow } 1239*4bff34e3Sthurlow 1240*4bff34e3Sthurlow 1241*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 1242*4bff34e3Sthurlow // 1243*4bff34e3Sthurlow // Function: 1244*4bff34e3Sthurlow // InitSpnegoTokenElements 1245*4bff34e3Sthurlow // 1246*4bff34e3Sthurlow // Parameters: 1247*4bff34e3Sthurlow // [in] pSpnegoToken - Points to SPNEGO_TOKEN struct 1248*4bff34e3Sthurlow // [in] pbTokenData - Points to initial binary element 1249*4bff34e3Sthurlow // data in a SPNEGO token. 1250*4bff34e3Sthurlow // [in] nRemainingTokenLength - Length remaining past header 1251*4bff34e3Sthurlow // 1252*4bff34e3Sthurlow // Returns: 1253*4bff34e3Sthurlow // int Success - SPNEGO_E_SUCCESS 1254*4bff34e3Sthurlow // Failure - SPNEGO API Error code 1255*4bff34e3Sthurlow // 1256*4bff34e3Sthurlow // Comments : 1257*4bff34e3Sthurlow // Interprets the data at pbTokenData based on the TokenType in 1258*4bff34e3Sthurlow // pSpnegoToken. Since some elements are optional (technically all are 1259*4bff34e3Sthurlow // but the token becomes quite useless if this is so), we check if 1260*4bff34e3Sthurlow // an element exists before filling out the element in the array. 1261*4bff34e3Sthurlow // 1262*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 1263*4bff34e3Sthurlow 1264*4bff34e3Sthurlow int InitSpnegoTokenElements( SPNEGO_TOKEN* pSpnegoToken, unsigned char* pbTokenData, 1265*4bff34e3Sthurlow long nRemainingTokenLength ) 1266*4bff34e3Sthurlow { 1267*4bff34e3Sthurlow // 1268*4bff34e3Sthurlow // The following arrays contain the token identifiers for the elements 1269*4bff34e3Sthurlow // comprising the actual token. All values are optional, and there are 1270*4bff34e3Sthurlow // no defaults. 1271*4bff34e3Sthurlow // 1272*4bff34e3Sthurlow 1273*4bff34e3Sthurlow static unsigned char abNegTokenInitElements[] = 1274*4bff34e3Sthurlow { SPNEGO_NEGINIT_ELEMENT_MECHTYPES, SPNEGO_NEGINIT_ELEMENT_REQFLAGS, 1275*4bff34e3Sthurlow SPNEGO_NEGINIT_ELEMENT_MECHTOKEN, SPNEGO_NEGINIT_ELEMENT_MECHLISTMIC }; 1276*4bff34e3Sthurlow 1277*4bff34e3Sthurlow static unsigned char abNegTokenTargElements[] = 1278*4bff34e3Sthurlow { SPNEGO_NEGTARG_ELEMENT_NEGRESULT, SPNEGO_NEGTARG_ELEMENT_SUPPORTEDMECH, 1279*4bff34e3Sthurlow SPNEGO_NEGTARG_ELEMENT_RESPONSETOKEN, SPNEGO_NEGTARG_ELEMENT_MECHLISTMIC }; 1280*4bff34e3Sthurlow 1281*4bff34e3Sthurlow int nReturn = SPNEGO_E_SUCCESS; 1282*4bff34e3Sthurlow int nCtr = 0L; 1283*4bff34e3Sthurlow long nElementLength = 0L; 1284*4bff34e3Sthurlow long nActualTokenLength = 0L; 1285*4bff34e3Sthurlow unsigned char* pbElements = NULL; 1286*4bff34e3Sthurlow unsigned char * ptok; 1287*4bff34e3Sthurlow long tlen, elen, len; 1288*4bff34e3Sthurlow 1289*4bff34e3Sthurlow // Point to the correct array 1290*4bff34e3Sthurlow switch( pSpnegoToken->ucTokenType ) 1291*4bff34e3Sthurlow { 1292*4bff34e3Sthurlow case SPNEGO_TOKEN_INIT: 1293*4bff34e3Sthurlow { 1294*4bff34e3Sthurlow pbElements = abNegTokenInitElements; 1295*4bff34e3Sthurlow } 1296*4bff34e3Sthurlow break; 1297*4bff34e3Sthurlow 1298*4bff34e3Sthurlow case SPNEGO_TOKEN_TARG: 1299*4bff34e3Sthurlow { 1300*4bff34e3Sthurlow pbElements = abNegTokenTargElements; 1301*4bff34e3Sthurlow } 1302*4bff34e3Sthurlow break; 1303*4bff34e3Sthurlow 1304*4bff34e3Sthurlow } // SWITCH tokentype 1305*4bff34e3Sthurlow 1306*4bff34e3Sthurlow // 1307*4bff34e3Sthurlow // Enumerate the element arrays and look for the tokens at our current location 1308*4bff34e3Sthurlow // 1309*4bff34e3Sthurlow 1310*4bff34e3Sthurlow for ( nCtr = 0L; 1311*4bff34e3Sthurlow SPNEGO_E_SUCCESS == nReturn && 1312*4bff34e3Sthurlow nCtr < MAX_NUM_TOKEN_ELEMENTS && 1313*4bff34e3Sthurlow nRemainingTokenLength > 0L; 1314*4bff34e3Sthurlow nCtr++ ) 1315*4bff34e3Sthurlow { 1316*4bff34e3Sthurlow 1317*4bff34e3Sthurlow // Check if the token exists 1318*4bff34e3Sthurlow if ( ( nReturn = ASNDerCheckToken( pbTokenData, pbElements[nCtr], 1319*4bff34e3Sthurlow 0L, nRemainingTokenLength, 1320*4bff34e3Sthurlow &nElementLength, &nActualTokenLength ) ) 1321*4bff34e3Sthurlow == SPNEGO_E_SUCCESS ) 1322*4bff34e3Sthurlow { 1323*4bff34e3Sthurlow 1324*4bff34e3Sthurlow // Token data should skip over the sequence token and then 1325*4bff34e3Sthurlow // call the appropriate function to initialize the element 1326*4bff34e3Sthurlow pbTokenData += nActualTokenLength; 1327*4bff34e3Sthurlow 1328*4bff34e3Sthurlow // Lengths in the elements should NOT go beyond the element 1329*4bff34e3Sthurlow // length 1330*4bff34e3Sthurlow 1331*4bff34e3Sthurlow // Different tokens mean different elements 1332*4bff34e3Sthurlow if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType ) 1333*4bff34e3Sthurlow { 1334*4bff34e3Sthurlow 1335*4bff34e3Sthurlow // Handle each element as appropriate 1336*4bff34e3Sthurlow switch( pbElements[nCtr] ) 1337*4bff34e3Sthurlow { 1338*4bff34e3Sthurlow 1339*4bff34e3Sthurlow case SPNEGO_NEGINIT_ELEMENT_MECHTYPES: 1340*4bff34e3Sthurlow { 1341*4bff34e3Sthurlow // 1342*4bff34e3Sthurlow // This is a Mech List that specifies which OIDs the 1343*4bff34e3Sthurlow // originator of the Init Token supports. 1344*4bff34e3Sthurlow // 1345*4bff34e3Sthurlow 1346*4bff34e3Sthurlow nReturn = GetSpnegoInitTokenMechList( pbTokenData, nElementLength, 1347*4bff34e3Sthurlow &pSpnegoToken->aElementArray[nCtr] ); 1348*4bff34e3Sthurlow 1349*4bff34e3Sthurlow } 1350*4bff34e3Sthurlow break; 1351*4bff34e3Sthurlow 1352*4bff34e3Sthurlow case SPNEGO_NEGINIT_ELEMENT_REQFLAGS: 1353*4bff34e3Sthurlow { 1354*4bff34e3Sthurlow // 1355*4bff34e3Sthurlow // This is a BITSTRING which specifies the flags that the receiver 1356*4bff34e3Sthurlow // pass to the gss_accept_sec_context() function. 1357*4bff34e3Sthurlow // 1358*4bff34e3Sthurlow 1359*4bff34e3Sthurlow nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength, 1360*4bff34e3Sthurlow BITSTRING, spnego_init_reqFlags, 1361*4bff34e3Sthurlow &pSpnegoToken->aElementArray[nCtr] ); 1362*4bff34e3Sthurlow } 1363*4bff34e3Sthurlow break; 1364*4bff34e3Sthurlow 1365*4bff34e3Sthurlow case SPNEGO_NEGINIT_ELEMENT_MECHTOKEN: 1366*4bff34e3Sthurlow { 1367*4bff34e3Sthurlow // 1368*4bff34e3Sthurlow // This is an OCTETSTRING which contains a GSSAPI token corresponding 1369*4bff34e3Sthurlow // to the first OID in the MechList. 1370*4bff34e3Sthurlow // 1371*4bff34e3Sthurlow 1372*4bff34e3Sthurlow nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength, 1373*4bff34e3Sthurlow OCTETSTRING, spnego_init_mechToken, 1374*4bff34e3Sthurlow &pSpnegoToken->aElementArray[nCtr] ); 1375*4bff34e3Sthurlow } 1376*4bff34e3Sthurlow break; 1377*4bff34e3Sthurlow 1378*4bff34e3Sthurlow case SPNEGO_NEGINIT_ELEMENT_MECHLISTMIC: 1379*4bff34e3Sthurlow { 1380*4bff34e3Sthurlow // 1381*4bff34e3Sthurlow // This is an OCTETSTRING which contains a message integrity BLOB. 1382*4bff34e3Sthurlow // 1383*4bff34e3Sthurlow 1384*4bff34e3Sthurlow nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength, 1385*4bff34e3Sthurlow OCTETSTRING, spnego_init_mechListMIC, 1386*4bff34e3Sthurlow &pSpnegoToken->aElementArray[nCtr] ); 1387*4bff34e3Sthurlow /* 1388*4bff34e3Sthurlow * don't believe everything you read in RFCs (and MS 1389*4bff34e3Sthurlow * sample code)... win2k is sending not an octet string, 1390*4bff34e3Sthurlow * but a "general string", wrapped in a sequence. 1391*4bff34e3Sthurlow */ 1392*4bff34e3Sthurlow if (nReturn != SPNEGO_E_UNEXPECTED_TYPE) 1393*4bff34e3Sthurlow break; 1394*4bff34e3Sthurlow ptok = pbTokenData; 1395*4bff34e3Sthurlow elen = nElementLength; 1396*4bff34e3Sthurlow if ((nReturn = ASNDerCheckToken(ptok, SPNEGO_CONSTRUCTED_SEQUENCE, elen, elen, &len, &tlen)) != SPNEGO_E_SUCCESS) 1397*4bff34e3Sthurlow break; 1398*4bff34e3Sthurlow elen -= tlen; 1399*4bff34e3Sthurlow ptok += tlen; 1400*4bff34e3Sthurlow 1401*4bff34e3Sthurlow if ((nReturn = ASNDerCheckToken(ptok, SEQ_ELM(0), elen, elen, &len, &tlen)) != SPNEGO_E_SUCCESS) 1402*4bff34e3Sthurlow break; 1403*4bff34e3Sthurlow elen -= tlen; 1404*4bff34e3Sthurlow ptok += tlen; 1405*4bff34e3Sthurlow nReturn = InitSpnegoTokenElementFromBasicType(ptok, elen, GENERALSTR, spnego_init_mechListMIC, &pSpnegoToken->aElementArray[nCtr]); 1406*4bff34e3Sthurlow } 1407*4bff34e3Sthurlow break; 1408*4bff34e3Sthurlow 1409*4bff34e3Sthurlow } // SWITCH Element 1410*4bff34e3Sthurlow } 1411*4bff34e3Sthurlow else 1412*4bff34e3Sthurlow { 1413*4bff34e3Sthurlow 1414*4bff34e3Sthurlow switch( pbElements[nCtr] ) 1415*4bff34e3Sthurlow { 1416*4bff34e3Sthurlow 1417*4bff34e3Sthurlow case SPNEGO_NEGTARG_ELEMENT_NEGRESULT: 1418*4bff34e3Sthurlow { 1419*4bff34e3Sthurlow // 1420*4bff34e3Sthurlow // This is an ENUMERATION which specifies result of the last GSS 1421*4bff34e3Sthurlow // token negotiation call. 1422*4bff34e3Sthurlow // 1423*4bff34e3Sthurlow 1424*4bff34e3Sthurlow nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength, 1425*4bff34e3Sthurlow ENUMERATED, spnego_targ_negResult, 1426*4bff34e3Sthurlow &pSpnegoToken->aElementArray[nCtr] ); 1427*4bff34e3Sthurlow } 1428*4bff34e3Sthurlow break; 1429*4bff34e3Sthurlow 1430*4bff34e3Sthurlow case SPNEGO_NEGTARG_ELEMENT_SUPPORTEDMECH: 1431*4bff34e3Sthurlow { 1432*4bff34e3Sthurlow // 1433*4bff34e3Sthurlow // This is an OID which specifies a supported mechanism. 1434*4bff34e3Sthurlow // 1435*4bff34e3Sthurlow 1436*4bff34e3Sthurlow nReturn = InitSpnegoTokenElementFromOID( pbTokenData, nElementLength, 1437*4bff34e3Sthurlow spnego_targ_mechListMIC, 1438*4bff34e3Sthurlow &pSpnegoToken->aElementArray[nCtr] ); 1439*4bff34e3Sthurlow } 1440*4bff34e3Sthurlow break; 1441*4bff34e3Sthurlow 1442*4bff34e3Sthurlow case SPNEGO_NEGTARG_ELEMENT_RESPONSETOKEN: 1443*4bff34e3Sthurlow { 1444*4bff34e3Sthurlow // 1445*4bff34e3Sthurlow // This is an OCTETSTRING which specifies results of the last GSS 1446*4bff34e3Sthurlow // token negotiation call. 1447*4bff34e3Sthurlow // 1448*4bff34e3Sthurlow 1449*4bff34e3Sthurlow nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength, 1450*4bff34e3Sthurlow OCTETSTRING, spnego_targ_responseToken, 1451*4bff34e3Sthurlow &pSpnegoToken->aElementArray[nCtr] ); 1452*4bff34e3Sthurlow } 1453*4bff34e3Sthurlow break; 1454*4bff34e3Sthurlow 1455*4bff34e3Sthurlow case SPNEGO_NEGTARG_ELEMENT_MECHLISTMIC: 1456*4bff34e3Sthurlow { 1457*4bff34e3Sthurlow // 1458*4bff34e3Sthurlow // This is an OCTETSTRING which specifies a message integrity BLOB. 1459*4bff34e3Sthurlow // 1460*4bff34e3Sthurlow 1461*4bff34e3Sthurlow nReturn = InitSpnegoTokenElementFromBasicType( pbTokenData, nElementLength, 1462*4bff34e3Sthurlow OCTETSTRING, spnego_targ_mechListMIC, 1463*4bff34e3Sthurlow &pSpnegoToken->aElementArray[nCtr] ); 1464*4bff34e3Sthurlow } 1465*4bff34e3Sthurlow break; 1466*4bff34e3Sthurlow 1467*4bff34e3Sthurlow } // SWITCH Element 1468*4bff34e3Sthurlow 1469*4bff34e3Sthurlow } // ELSE !NegTokenInit 1470*4bff34e3Sthurlow 1471*4bff34e3Sthurlow // Account for the entire token and following data 1472*4bff34e3Sthurlow nRemainingTokenLength -= ( nActualTokenLength + nElementLength ); 1473*4bff34e3Sthurlow 1474*4bff34e3Sthurlow // Token data should skip past the element length now 1475*4bff34e3Sthurlow pbTokenData += nElementLength; 1476*4bff34e3Sthurlow 1477*4bff34e3Sthurlow } // IF Token found 1478*4bff34e3Sthurlow else if ( SPNEGO_E_TOKEN_NOT_FOUND == nReturn ) 1479*4bff34e3Sthurlow { 1480*4bff34e3Sthurlow // For now, this is a benign error (remember, all elements are optional, so 1481*4bff34e3Sthurlow // if we don't find one, it's okay). 1482*4bff34e3Sthurlow 1483*4bff34e3Sthurlow nReturn = SPNEGO_E_SUCCESS; 1484*4bff34e3Sthurlow } 1485*4bff34e3Sthurlow 1486*4bff34e3Sthurlow } // FOR enum elements 1487*4bff34e3Sthurlow 1488*4bff34e3Sthurlow // 1489*4bff34e3Sthurlow // We should always run down to 0 remaining bytes in the token. If not, we've got 1490*4bff34e3Sthurlow // a bad token. 1491*4bff34e3Sthurlow // 1492*4bff34e3Sthurlow 1493*4bff34e3Sthurlow if ( SPNEGO_E_SUCCESS == nReturn && nRemainingTokenLength != 0L ) 1494*4bff34e3Sthurlow { 1495*4bff34e3Sthurlow nReturn = SPNEGO_E_INVALID_TOKEN; 1496*4bff34e3Sthurlow } 1497*4bff34e3Sthurlow 1498*4bff34e3Sthurlow return nReturn; 1499*4bff34e3Sthurlow } 1500*4bff34e3Sthurlow 1501*4bff34e3Sthurlow 1502*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 1503*4bff34e3Sthurlow // 1504*4bff34e3Sthurlow // Function: 1505*4bff34e3Sthurlow // FindMechOIDInMechList 1506*4bff34e3Sthurlow // 1507*4bff34e3Sthurlow // Parameters: 1508*4bff34e3Sthurlow // [in] pSpnegoElement - SPNEGO_ELEMENT for MechList 1509*4bff34e3Sthurlow // [in] MechOID - OID we're looking for. 1510*4bff34e3Sthurlow // [out] piMechTypeIndex - Index in the list where OID was 1511*4bff34e3Sthurlow // found 1512*4bff34e3Sthurlow // 1513*4bff34e3Sthurlow // Returns: 1514*4bff34e3Sthurlow // int Success - SPNEGO_E_SUCCESS 1515*4bff34e3Sthurlow // Failure - SPNEGO API Error code 1516*4bff34e3Sthurlow // 1517*4bff34e3Sthurlow // Comments : 1518*4bff34e3Sthurlow // Walks the MechList for MechOID. When it is found, the index in the 1519*4bff34e3Sthurlow // list is written to piMechTypeIndex. 1520*4bff34e3Sthurlow // 1521*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 1522*4bff34e3Sthurlow 1523*4bff34e3Sthurlow int FindMechOIDInMechList( SPNEGO_ELEMENT* pSpnegoElement, SPNEGO_MECH_OID MechOID, 1524*4bff34e3Sthurlow int * piMechTypeIndex ) 1525*4bff34e3Sthurlow { 1526*4bff34e3Sthurlow int nReturn = SPNEGO_E_NOT_FOUND; 1527*4bff34e3Sthurlow int nCtr = 0; 1528*4bff34e3Sthurlow long nLength = 0L; 1529*4bff34e3Sthurlow long nBoundaryLength = pSpnegoElement->nDatalength; 1530*4bff34e3Sthurlow unsigned char* pbMechListData = pSpnegoElement->pbData; 1531*4bff34e3Sthurlow 1532*4bff34e3Sthurlow while( SPNEGO_E_SUCCESS != nReturn && nBoundaryLength > 0L ) 1533*4bff34e3Sthurlow { 1534*4bff34e3Sthurlow 1535*4bff34e3Sthurlow // Use the helper function to check the OID 1536*4bff34e3Sthurlow if ( ( nReturn = ASNDerCheckOID( pbMechListData, MechOID, nBoundaryLength, &nLength ) ) 1537*4bff34e3Sthurlow == SPNEGO_E_SUCCESS ) 1538*4bff34e3Sthurlow { 1539*4bff34e3Sthurlow *piMechTypeIndex = nCtr; 1540*4bff34e3Sthurlow } 1541*4bff34e3Sthurlow 1542*4bff34e3Sthurlow // Adjust for the current OID 1543*4bff34e3Sthurlow pbMechListData += nLength; 1544*4bff34e3Sthurlow nBoundaryLength -= nLength; 1545*4bff34e3Sthurlow nCtr++; 1546*4bff34e3Sthurlow 1547*4bff34e3Sthurlow } // WHILE enuming OIDs 1548*4bff34e3Sthurlow 1549*4bff34e3Sthurlow return nReturn; 1550*4bff34e3Sthurlow 1551*4bff34e3Sthurlow } 1552*4bff34e3Sthurlow 1553*4bff34e3Sthurlow 1554*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 1555*4bff34e3Sthurlow // 1556*4bff34e3Sthurlow // Function: 1557*4bff34e3Sthurlow // ValidateMechList 1558*4bff34e3Sthurlow // 1559*4bff34e3Sthurlow // Parameters: 1560*4bff34e3Sthurlow // [in] pbMechListData - Pointer to binary MechList data 1561*4bff34e3Sthurlow // [in] nBoundaryLength - Length we must not exceed 1562*4bff34e3Sthurlow // 1563*4bff34e3Sthurlow // Returns: 1564*4bff34e3Sthurlow // int Success - SPNEGO_E_SUCCESS 1565*4bff34e3Sthurlow // Failure - SPNEGO API Error code 1566*4bff34e3Sthurlow // 1567*4bff34e3Sthurlow // Comments : 1568*4bff34e3Sthurlow // Checks the data at pbMechListData to see if it looks like a MechList. 1569*4bff34e3Sthurlow // As part of this, we walk the list and ensure that none of the OIDs 1570*4bff34e3Sthurlow // have a length that takes us outside of nBoundaryLength. 1571*4bff34e3Sthurlow // 1572*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 1573*4bff34e3Sthurlow 1574*4bff34e3Sthurlow int ValidateMechList( unsigned char* pbMechListData, long nBoundaryLength ) 1575*4bff34e3Sthurlow { 1576*4bff34e3Sthurlow int nReturn = SPNEGO_E_SUCCESS; 1577*4bff34e3Sthurlow long nLength = 0L; 1578*4bff34e3Sthurlow long nTokenLength = 0L; 1579*4bff34e3Sthurlow 1580*4bff34e3Sthurlow while( SPNEGO_E_SUCCESS == nReturn && nBoundaryLength > 0L ) 1581*4bff34e3Sthurlow { 1582*4bff34e3Sthurlow // Verify that we have something that at least *looks* like an OID - in other 1583*4bff34e3Sthurlow // words it has an OID identifier and specifies a length that doesn't go beyond 1584*4bff34e3Sthurlow // the size of the list. 1585*4bff34e3Sthurlow nReturn = ASNDerCheckToken( pbMechListData, OID, 0L, nBoundaryLength, 1586*4bff34e3Sthurlow &nLength, &nTokenLength ); 1587*4bff34e3Sthurlow 1588*4bff34e3Sthurlow // Adjust for the current OID 1589*4bff34e3Sthurlow pbMechListData += ( nLength + nTokenLength ); 1590*4bff34e3Sthurlow nBoundaryLength -= ( nLength + nTokenLength ); 1591*4bff34e3Sthurlow 1592*4bff34e3Sthurlow } // WHILE enuming OIDs 1593*4bff34e3Sthurlow 1594*4bff34e3Sthurlow return nReturn; 1595*4bff34e3Sthurlow 1596*4bff34e3Sthurlow } 1597*4bff34e3Sthurlow 1598*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 1599*4bff34e3Sthurlow // 1600*4bff34e3Sthurlow // Function: 1601*4bff34e3Sthurlow // IsValidMechOid 1602*4bff34e3Sthurlow // 1603*4bff34e3Sthurlow // Parameters: 1604*4bff34e3Sthurlow // [in] mechOid - mechOID id enumeration 1605*4bff34e3Sthurlow // 1606*4bff34e3Sthurlow // Returns: 1607*4bff34e3Sthurlow // int Success - 1 1608*4bff34e3Sthurlow // Failure - 0 1609*4bff34e3Sthurlow // 1610*4bff34e3Sthurlow // Comments : 1611*4bff34e3Sthurlow // Checks for a valid mechOid value. 1612*4bff34e3Sthurlow // 1613*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 1614*4bff34e3Sthurlow 1615*4bff34e3Sthurlow int IsValidMechOid( SPNEGO_MECH_OID mechOid ) 1616*4bff34e3Sthurlow { 1617*4bff34e3Sthurlow return ( mechOid >= spnego_mech_oid_Kerberos_V5_Legacy && 1618*4bff34e3Sthurlow mechOid <= spnego_mech_oid_Spnego ); 1619*4bff34e3Sthurlow } 1620*4bff34e3Sthurlow 1621*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 1622*4bff34e3Sthurlow // 1623*4bff34e3Sthurlow // Function: 1624*4bff34e3Sthurlow // IsValidContextFlags 1625*4bff34e3Sthurlow // 1626*4bff34e3Sthurlow // Parameters: 1627*4bff34e3Sthurlow // [in] ucContextFlags - ContextFlags value 1628*4bff34e3Sthurlow // 1629*4bff34e3Sthurlow // Returns: 1630*4bff34e3Sthurlow // int Success - 1 1631*4bff34e3Sthurlow // Failure - 0 1632*4bff34e3Sthurlow // 1633*4bff34e3Sthurlow // Comments : 1634*4bff34e3Sthurlow // Checks for a valid ContextFlags value. 1635*4bff34e3Sthurlow // 1636*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 1637*4bff34e3Sthurlow 1638*4bff34e3Sthurlow int IsValidContextFlags( unsigned char ucContextFlags ) 1639*4bff34e3Sthurlow { 1640*4bff34e3Sthurlow // Mask out our valid bits. If there is anything leftover, this 1641*4bff34e3Sthurlow // is not a valid value for Context Flags 1642*4bff34e3Sthurlow return ( ( ucContextFlags & ~SPNEGO_NEGINIT_CONTEXT_MASK ) == 0 ); 1643*4bff34e3Sthurlow } 1644*4bff34e3Sthurlow 1645*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 1646*4bff34e3Sthurlow // 1647*4bff34e3Sthurlow // Function: 1648*4bff34e3Sthurlow // IsValidNegResult 1649*4bff34e3Sthurlow // 1650*4bff34e3Sthurlow // Parameters: 1651*4bff34e3Sthurlow // [in] negResult - NegResult value 1652*4bff34e3Sthurlow // 1653*4bff34e3Sthurlow // Returns: 1654*4bff34e3Sthurlow // int Success - 1 1655*4bff34e3Sthurlow // Failure - 0 1656*4bff34e3Sthurlow // 1657*4bff34e3Sthurlow // Comments : 1658*4bff34e3Sthurlow // Checks for a valid NegResult value. 1659*4bff34e3Sthurlow // 1660*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 1661*4bff34e3Sthurlow 1662*4bff34e3Sthurlow int IsValidNegResult( SPNEGO_NEGRESULT negResult ) 1663*4bff34e3Sthurlow { 1664*4bff34e3Sthurlow return ( negResult >= spnego_negresult_success && 1665*4bff34e3Sthurlow negResult <= spnego_negresult_rejected ); 1666*4bff34e3Sthurlow } 1667*4bff34e3Sthurlow 1668*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 1669*4bff34e3Sthurlow // 1670*4bff34e3Sthurlow // Function: 1671*4bff34e3Sthurlow // IsValidSpnegoToken 1672*4bff34e3Sthurlow // 1673*4bff34e3Sthurlow // Parameters: 1674*4bff34e3Sthurlow // [in] pSpnegoToken - Points to SPNEGO_TOKEN data structure 1675*4bff34e3Sthurlow // 1676*4bff34e3Sthurlow // Returns: 1677*4bff34e3Sthurlow // int Success - 1 1678*4bff34e3Sthurlow // Failure - 0 1679*4bff34e3Sthurlow // 1680*4bff34e3Sthurlow // Comments : 1681*4bff34e3Sthurlow // Performs simple heuristic on location pointed to by pSpnegoToken. 1682*4bff34e3Sthurlow // 1683*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 1684*4bff34e3Sthurlow 1685*4bff34e3Sthurlow int IsValidSpnegoToken( SPNEGO_TOKEN* pSpnegoToken ) 1686*4bff34e3Sthurlow { 1687*4bff34e3Sthurlow int nReturn = 0; 1688*4bff34e3Sthurlow 1689*4bff34e3Sthurlow // Parameter should be non-NULL 1690*4bff34e3Sthurlow if ( NULL != pSpnegoToken ) 1691*4bff34e3Sthurlow { 1692*4bff34e3Sthurlow // Length should be at least the size defined in the header 1693*4bff34e3Sthurlow if ( pSpnegoToken->nStructSize >= SPNEGO_TOKEN_SIZE ) 1694*4bff34e3Sthurlow { 1695*4bff34e3Sthurlow // Number of elements should be >= our maximum - if it's greater, that's 1696*4bff34e3Sthurlow // okay, since we'll only be accessing the elements up to MAX_NUM_TOKEN_ELEMENTS 1697*4bff34e3Sthurlow if ( pSpnegoToken->nNumElements >= MAX_NUM_TOKEN_ELEMENTS ) 1698*4bff34e3Sthurlow { 1699*4bff34e3Sthurlow // Check for proper token type 1700*4bff34e3Sthurlow if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType || 1701*4bff34e3Sthurlow SPNEGO_TOKEN_TARG == pSpnegoToken->ucTokenType ) 1702*4bff34e3Sthurlow { 1703*4bff34e3Sthurlow nReturn = 1; 1704*4bff34e3Sthurlow } 1705*4bff34e3Sthurlow } 1706*4bff34e3Sthurlow 1707*4bff34e3Sthurlow } // IF struct size makes sense 1708*4bff34e3Sthurlow 1709*4bff34e3Sthurlow } // IF non-NULL spnego Token 1710*4bff34e3Sthurlow 1711*4bff34e3Sthurlow return nReturn; 1712*4bff34e3Sthurlow } 1713*4bff34e3Sthurlow 1714*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 1715*4bff34e3Sthurlow // 1716*4bff34e3Sthurlow // Function: 1717*4bff34e3Sthurlow // IsValidSpnegoElement 1718*4bff34e3Sthurlow // 1719*4bff34e3Sthurlow // Parameters: 1720*4bff34e3Sthurlow // [in] pSpnegoToken - Points to SPNEGO_TOKEN data structure 1721*4bff34e3Sthurlow // [in] spnegoElement - spnegoElement Type from enumeration 1722*4bff34e3Sthurlow // 1723*4bff34e3Sthurlow // Returns: 1724*4bff34e3Sthurlow // int Success - 1 1725*4bff34e3Sthurlow // Failure - 0 1726*4bff34e3Sthurlow // 1727*4bff34e3Sthurlow // Comments : 1728*4bff34e3Sthurlow // Checks that spnegoElement has a valid value and is appropriate for 1729*4bff34e3Sthurlow // the SPNEGO token encapsulated by pSpnegoToken. 1730*4bff34e3Sthurlow // 1731*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 1732*4bff34e3Sthurlow 1733*4bff34e3Sthurlow int IsValidSpnegoElement( SPNEGO_TOKEN* pSpnegoToken,SPNEGO_ELEMENT_TYPE spnegoElement ) 1734*4bff34e3Sthurlow { 1735*4bff34e3Sthurlow int nReturn = 0; 1736*4bff34e3Sthurlow 1737*4bff34e3Sthurlow // Check boundaries 1738*4bff34e3Sthurlow if ( spnegoElement > spnego_element_min && 1739*4bff34e3Sthurlow spnegoElement < spnego_element_max ) 1740*4bff34e3Sthurlow { 1741*4bff34e3Sthurlow 1742*4bff34e3Sthurlow // Check for appropriateness to token type 1743*4bff34e3Sthurlow if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType ) 1744*4bff34e3Sthurlow { 1745*4bff34e3Sthurlow nReturn = ( spnegoElement >= spnego_init_mechtypes && 1746*4bff34e3Sthurlow spnegoElement <= spnego_init_mechListMIC ); 1747*4bff34e3Sthurlow } 1748*4bff34e3Sthurlow else 1749*4bff34e3Sthurlow { 1750*4bff34e3Sthurlow nReturn = ( spnegoElement >= spnego_targ_negResult && 1751*4bff34e3Sthurlow spnegoElement <= spnego_targ_mechListMIC ); 1752*4bff34e3Sthurlow } 1753*4bff34e3Sthurlow 1754*4bff34e3Sthurlow } // IF boundary conditions are met 1755*4bff34e3Sthurlow 1756*4bff34e3Sthurlow return nReturn; 1757*4bff34e3Sthurlow } 1758*4bff34e3Sthurlow 1759*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 1760*4bff34e3Sthurlow // 1761*4bff34e3Sthurlow // Function: 1762*4bff34e3Sthurlow // CalculateElementArrayIndex 1763*4bff34e3Sthurlow // 1764*4bff34e3Sthurlow // Parameters: 1765*4bff34e3Sthurlow // [in] pSpnegoToken - Points to SPNEGO_TOKEN data structure 1766*4bff34e3Sthurlow // [in] spnegoElement - spnegoElement Type from enumeration 1767*4bff34e3Sthurlow // 1768*4bff34e3Sthurlow // Returns: 1769*4bff34e3Sthurlow // int index in the SPNEGO_TOKEN element array that the element can 1770*4bff34e3Sthurlow // can be found 1771*4bff34e3Sthurlow // 1772*4bff34e3Sthurlow // Comments : 1773*4bff34e3Sthurlow // Based on the Token Type, calculates the index in the element array 1774*4bff34e3Sthurlow // at which the specified element can be found. 1775*4bff34e3Sthurlow // 1776*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 1777*4bff34e3Sthurlow 1778*4bff34e3Sthurlow int CalculateElementArrayIndex( SPNEGO_TOKEN* pSpnegoToken,SPNEGO_ELEMENT_TYPE spnegoElement ) 1779*4bff34e3Sthurlow { 1780*4bff34e3Sthurlow int nReturn = 0; 1781*4bff34e3Sthurlow 1782*4bff34e3Sthurlow // Offset is difference between value and initial element identifier 1783*4bff34e3Sthurlow // (these differ based on ucTokenType) 1784*4bff34e3Sthurlow 1785*4bff34e3Sthurlow if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType ) 1786*4bff34e3Sthurlow { 1787*4bff34e3Sthurlow nReturn = spnegoElement - spnego_init_mechtypes; 1788*4bff34e3Sthurlow } 1789*4bff34e3Sthurlow else 1790*4bff34e3Sthurlow { 1791*4bff34e3Sthurlow nReturn = spnegoElement - spnego_targ_negResult; 1792*4bff34e3Sthurlow } 1793*4bff34e3Sthurlow 1794*4bff34e3Sthurlow return nReturn; 1795*4bff34e3Sthurlow } 1796*4bff34e3Sthurlow 1797*4bff34e3Sthurlow ///////////////////////////////////////////////////////////////////////////// 1798*4bff34e3Sthurlow // 1799*4bff34e3Sthurlow // Function: 1800*4bff34e3Sthurlow // InitTokenFromBinary 1801*4bff34e3Sthurlow // 1802*4bff34e3Sthurlow // Parameters: 1803*4bff34e3Sthurlow // [in] ucCopyData - Flag indicating if data should be copied 1804*4bff34e3Sthurlow // [in] ulFlags - Flags value for structure 1805*4bff34e3Sthurlow // [in] pnTokenData - Binary Token Data 1806*4bff34e3Sthurlow // [in] ulLength - Length of the data 1807*4bff34e3Sthurlow // [out] ppSpnegoToken - Pointer to call allocated SPNEGO Token 1808*4bff34e3Sthurlow // data structure 1809*4bff34e3Sthurlow // 1810*4bff34e3Sthurlow // Returns: 1811*4bff34e3Sthurlow // int Success - SPNEGO_E_SUCCESS 1812*4bff34e3Sthurlow // Failure - SPNEGO API Error code 1813*4bff34e3Sthurlow // 1814*4bff34e3Sthurlow // Comments : 1815*4bff34e3Sthurlow // Allocates a SPNEGO_TOKEN data structure and fills it out as 1816*4bff34e3Sthurlow // appropriate based in the flags passed into the function. 1817*4bff34e3Sthurlow // 1818*4bff34e3Sthurlow //////////////////////////////////////////////////////////////////////////// 1819*4bff34e3Sthurlow 1820*4bff34e3Sthurlow 1821*4bff34e3Sthurlow // Initializes SPNEGO_TOKEN structure from DER encoded binary data 1822*4bff34e3Sthurlow int InitTokenFromBinary( unsigned char ucCopyData, unsigned long ulFlags, 1823*4bff34e3Sthurlow unsigned char* pbTokenData, unsigned long ulLength, 1824*4bff34e3Sthurlow SPNEGO_TOKEN** ppSpnegoToken ) 1825*4bff34e3Sthurlow { 1826*4bff34e3Sthurlow int nReturn = SPNEGO_E_INVALID_PARAMETER; 1827*4bff34e3Sthurlow SPNEGO_TOKEN* pSpnegoToken = NULL; 1828*4bff34e3Sthurlow unsigned char* pbFirstElement = NULL; 1829*4bff34e3Sthurlow long nTokenLength = 0L; 1830*4bff34e3Sthurlow long nRemainingTokenLength = 0L; 1831*4bff34e3Sthurlow 1832*4bff34e3Sthurlow // Basic Parameter Validation 1833*4bff34e3Sthurlow 1834*4bff34e3Sthurlow if ( NULL != pbTokenData && 1835*4bff34e3Sthurlow NULL != ppSpnegoToken && 1836*4bff34e3Sthurlow 0L != ulLength ) 1837*4bff34e3Sthurlow { 1838*4bff34e3Sthurlow 1839*4bff34e3Sthurlow // 1840*4bff34e3Sthurlow // Allocate the empty token, then initialize the data structure. 1841*4bff34e3Sthurlow // 1842*4bff34e3Sthurlow 1843*4bff34e3Sthurlow pSpnegoToken = AllocEmptySpnegoToken( ucCopyData, ulFlags, pbTokenData, ulLength ); 1844*4bff34e3Sthurlow 1845*4bff34e3Sthurlow if ( NULL != pSpnegoToken ) 1846*4bff34e3Sthurlow { 1847*4bff34e3Sthurlow 1848*4bff34e3Sthurlow // Copy the binary data locally 1849*4bff34e3Sthurlow 1850*4bff34e3Sthurlow 1851*4bff34e3Sthurlow // Initialize the token type 1852*4bff34e3Sthurlow if ( ( nReturn = InitSpnegoTokenType( pSpnegoToken, &nTokenLength, 1853*4bff34e3Sthurlow &nRemainingTokenLength, &pbFirstElement ) ) 1854*4bff34e3Sthurlow == SPNEGO_E_SUCCESS ) 1855*4bff34e3Sthurlow { 1856*4bff34e3Sthurlow 1857*4bff34e3Sthurlow // Initialize the element array 1858*4bff34e3Sthurlow if ( ( nReturn = InitSpnegoTokenElements( pSpnegoToken, pbFirstElement, 1859*4bff34e3Sthurlow nRemainingTokenLength ) ) 1860*4bff34e3Sthurlow == SPNEGO_E_SUCCESS ) 1861*4bff34e3Sthurlow { 1862*4bff34e3Sthurlow *ppSpnegoToken = pSpnegoToken; 1863*4bff34e3Sthurlow } 1864*4bff34e3Sthurlow 1865*4bff34e3Sthurlow } // IF Init Token Type 1866*4bff34e3Sthurlow 1867*4bff34e3Sthurlow // Cleanup on error condition 1868*4bff34e3Sthurlow if ( SPNEGO_E_SUCCESS != nReturn ) 1869*4bff34e3Sthurlow { 1870*4bff34e3Sthurlow spnegoFreeData( pSpnegoToken ); 1871*4bff34e3Sthurlow } 1872*4bff34e3Sthurlow 1873*4bff34e3Sthurlow } 1874*4bff34e3Sthurlow else 1875*4bff34e3Sthurlow { 1876*4bff34e3Sthurlow nReturn = SPNEGO_E_OUT_OF_MEMORY; 1877*4bff34e3Sthurlow } 1878*4bff34e3Sthurlow 1879*4bff34e3Sthurlow } // IF Valid parameters 1880*4bff34e3Sthurlow 1881*4bff34e3Sthurlow 1882*4bff34e3Sthurlow return nReturn; 1883*4bff34e3Sthurlow } 1884