xref: /titanic_51/usr/src/lib/libsmbfs/smb/spnegoparse.c (revision 4bff34e37def8a90f9194d81bc345c52ba20086a)
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