1// Copyright (C) 2002 Microsoft Corporation
2// All rights reserved.
3//
4// THIS CODE AND INFORMATION IS PROVIDED "AS IS"
5// WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
6// OR IMPLIED, INCLUDING BUT NOT LIMITED
7// TO THE IMPLIED WARRANTIES OF MERCHANTIBILITY
8// AND/OR FITNESS FOR A PARTICULAR PURPOSE.
9//
10// Date    - 10/08/2002
11// Author  - Sanj Surati
12
13/////////////////////////////////////////////////////////////
14//
15// SPNEGO.C
16//
17// SPNEGO Token Handler Source File
18//
19// Contains implementation of SPNEGO Token Handling API
20// as defined in SPNEGO.H.
21//
22/////////////////////////////////////////////////////////////
23
24#pragma ident	"%Z%%M%	%I%	%E% SMI"
25
26#include <stdlib.h>
27#include <stdio.h>
28#include <memory.h>
29#include "spnego.h"
30#include "derparse.h"
31#include "spnegoparse.h"
32
33//
34// Defined in DERPARSE.C
35//
36
37extern MECH_OID g_stcMechOIDList [];
38
39
40/**********************************************************************/
41/**                                                                  **/
42/**                                                                  **/
43/**                                                                  **/
44/**                                                                  **/
45/**               SPNEGO Token Handler API implementation            **/
46/**                                                                  **/
47/**                                                                  **/
48/**                                                                  **/
49/**                                                                  **/
50/**********************************************************************/
51
52
53/////////////////////////////////////////////////////////////////////////////
54//
55// Function:
56//    spnegoInitFromBinary
57//
58// Parameters:
59//    [in]  pbTokenData       -  Binary Token Data
60//    [in]  ulLength          -  Length of binary Token Data
61//    [out] phSpnegoToken     -  SPNEGO_TOKEN_HANDLE pointer
62//
63// Returns:
64//    int   Success - SPNEGO_E_SUCCESS
65//          Failure - SPNEGO API Error code
66//
67// Comments :
68//    Initializes a SPNEGO_TOKEN_HANDLE from the supplied
69//    binary data.  Data is copied locally.  Returned data structure
70//    must be freed by calling spnegoFreeData().
71//
72////////////////////////////////////////////////////////////////////////////
73
74int spnegoInitFromBinary( unsigned char* pbTokenData, unsigned long ulLength, SPNEGO_TOKEN_HANDLE* phSpnegoToken )
75{
76   int            nReturn = SPNEGO_E_INVALID_PARAMETER;
77   SPNEGO_TOKEN** ppSpnegoToken = (SPNEGO_TOKEN**) phSpnegoToken;
78
79   // Pass off to a handler function that allows tighter control over how the token structure
80   // is handled.  In this case, we want the token data copied and we want the associated buffer
81   // freed.
82   nReturn = InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYDATA,
83                                 SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA, pbTokenData,
84                                 ulLength, ppSpnegoToken );
85
86   return nReturn;
87}
88
89/////////////////////////////////////////////////////////////////////////////
90//
91// Function:
92//    spnegoCreateNegTokenInit
93//
94// Parameters:
95//    [in]  MechType          -  MechType to specify in MechTypeList element
96//    [in]  ucContextFlags    -  Context Flags element value
97//    [in]  pbMechToken       -  Pointer to binary MechToken Data
98//    [in]  ulMechTokenLen    -  Length of MechToken Data
99//    [in]  pbMechListMIC     -  Pointer to binary MechListMIC Data
100//    [in]  ulMechListMICLen  -  Length of MechListMIC Data
101//    [out] phSpnegoToken     -  SPNEGO_TOKEN_HANDLE pointer
102//
103// Returns:
104//    int   Success - SPNEGO_E_SUCCESS
105//          Failure - SPNEGO API Error code
106//
107// Comments :
108//    Initializes a SPNEGO_TOKEN_HANDLE for a NegTokenInit type
109//    from the supplied parameters.  ucContextFlags may be 0 or must be
110//    a valid flag combination.  MechToken data can be NULL - if not, it
111//    must correspond to the MechType.  MechListMIC can also be NULL.
112//    Returned data structure must be freed by calling spnegoFreeData().
113//
114////////////////////////////////////////////////////////////////////////////
115
116int spnegoCreateNegTokenInit( SPNEGO_MECH_OID MechType,
117          unsigned char ucContextFlags, unsigned char* pbMechToken,
118          unsigned long ulMechTokenLen, unsigned char* pbMechListMIC,
119          unsigned long ulMechListMICLen, SPNEGO_TOKEN_HANDLE* phSpnegoToken )
120{
121   int   nReturn = SPNEGO_E_INVALID_PARAMETER;
122   long  nTokenLength = 0L;
123   long  nInternalTokenLength = 0L;
124   unsigned char* pbTokenData = NULL;
125   SPNEGO_TOKEN** ppSpnegoToken = (SPNEGO_TOKEN**) phSpnegoToken;
126
127   if ( NULL != ppSpnegoToken &&
128         IsValidMechOid( MechType ) &&
129         IsValidContextFlags( ucContextFlags ) )
130   {
131      // Get the actual token size
132
133      if ( ( nReturn = CalculateMinSpnegoInitTokenSize( ulMechTokenLen, ulMechListMICLen,
134                                                         MechType, ( ucContextFlags != 0L ),
135                                                         &nTokenLength, &nInternalTokenLength ) )
136                        == SPNEGO_E_SUCCESS )
137      {
138         // Allocate a buffer to hold the data.
139         pbTokenData = calloc( 1, nTokenLength );
140
141         if ( NULL != pbTokenData )
142         {
143
144            // Now write the token
145            if ( ( nReturn = CreateSpnegoInitToken( MechType,
146                                                 ucContextFlags, pbMechToken,
147                                                 ulMechTokenLen, pbMechListMIC,
148                                                 ulMechListMICLen, pbTokenData,
149                                                 nTokenLength, nInternalTokenLength ) )
150                              == SPNEGO_E_SUCCESS )
151            {
152
153               // This will copy our allocated pointer, and ensure that the sructure cleans
154               // up the data later
155               nReturn = InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYPTR,
156                                             SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA,
157                                             pbTokenData, nTokenLength, ppSpnegoToken );
158
159            }
160
161            // Cleanup on failure
162            if ( SPNEGO_E_SUCCESS != nReturn )
163            {
164               free( pbTokenData );
165            }
166
167         }  // IF alloc succeeded
168         else
169         {
170            nReturn = SPNEGO_E_OUT_OF_MEMORY;
171         }
172
173      }  // If calculated token size
174
175   }  // IF Valid Parameters
176
177   return nReturn;
178}
179
180/////////////////////////////////////////////////////////////////////////////
181//
182// Function:
183//    spnegoCreateNegTokenTarg
184//
185// Parameters:
186//    [in]  MechType          -  MechType to specify in supported MechType element
187//    [in]  spnegoNegResult   -  NegResult value
188//    [in]  pbMechToken       -  Pointer to response MechToken Data
189//    [in]  ulMechTokenLen    -  Length of MechToken Data
190//    [in]  pbMechListMIC     -  Pointer to binary MechListMIC Data
191//    [in]  ulMechListMICLen  -  Length of MechListMIC Data
192//    [out] phSpnegoToken     -  SPNEGO_TOKEN_HANDLE pointer
193//
194// Returns:
195//    int   Success - SPNEGO_E_SUCCESS
196//          Failure - SPNEGO API Error code
197//
198// Comments :
199//    Initializes a SPNEGO_TOKEN_HANDLE for a NegTokenTarg type
200//    from the supplied parameters.  MechToken data can be NULL - if not,
201//    it must correspond to the MechType.  MechListMIC can also be NULL.
202//    Returned data structure must be freed by calling spnegoFreeData().
203//
204////////////////////////////////////////////////////////////////////////////
205
206int spnegoCreateNegTokenTarg( SPNEGO_MECH_OID MechType,
207          SPNEGO_NEGRESULT spnegoNegResult, unsigned char* pbMechToken,
208          unsigned long ulMechTokenLen, unsigned char* pbMechListMIC,
209          unsigned long ulMechListMICLen, SPNEGO_TOKEN_HANDLE* phSpnegoToken )
210{
211   int   nReturn = SPNEGO_E_INVALID_PARAMETER;
212   long  nTokenLength = 0L;
213   long  nInternalTokenLength = 0L;
214   unsigned char* pbTokenData = NULL;
215   SPNEGO_TOKEN** ppSpnegoToken = (SPNEGO_TOKEN**) phSpnegoToken;
216
217   //
218   // spnego_mech_oid_NotUsed and spnego_negresult_NotUsed
219   // are okay here, however a valid MechOid is required
220   // if spnego_negresult_success or spnego_negresult_incomplete
221   // is specified.
222   //
223
224   if ( NULL != ppSpnegoToken &&
225
226         ( IsValidMechOid( MechType ) ||
227            spnego_mech_oid_NotUsed == MechType ) &&
228
229         ( IsValidNegResult( spnegoNegResult ) ||
230            spnego_negresult_NotUsed == spnegoNegResult ) &&
231
232         !( !IsValidMechOid( MechType ) &&
233            ( spnego_negresult_success == spnegoNegResult ||
234              spnego_negresult_incomplete == spnegoNegResult ) ) )
235   {
236
237      // Get the actual token size
238
239      if ( ( nReturn = CalculateMinSpnegoTargTokenSize( MechType, spnegoNegResult, ulMechTokenLen,
240                                                         ulMechListMICLen, &nTokenLength,
241                                                         &nInternalTokenLength ) )
242                        == SPNEGO_E_SUCCESS )
243      {
244         // Allocate a buffer to hold the data.
245         pbTokenData = calloc( 1, nTokenLength );
246
247         if ( NULL != pbTokenData )
248         {
249
250            // Now write the token
251            if ( ( nReturn = CreateSpnegoTargToken( MechType,
252                                                 spnegoNegResult, pbMechToken,
253                                                 ulMechTokenLen, pbMechListMIC,
254                                                 ulMechListMICLen, pbTokenData,
255                                                 nTokenLength, nInternalTokenLength ) )
256                              == SPNEGO_E_SUCCESS )
257            {
258
259               // This will copy our allocated pointer, and ensure that the sructure cleans
260               // up the data later
261               nReturn = InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYPTR,
262                                             SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA,
263                                             pbTokenData, nTokenLength, ppSpnegoToken );
264
265            }
266
267            // Cleanup on failure
268            if ( SPNEGO_E_SUCCESS != nReturn )
269            {
270               free( pbTokenData );
271            }
272
273         }  // IF alloc succeeded
274         else
275         {
276            nReturn = SPNEGO_E_OUT_OF_MEMORY;
277         }
278
279      }  // If calculated token size
280
281   }  // IF Valid Parameters
282
283   return nReturn;
284}
285
286/////////////////////////////////////////////////////////////////////////////
287//
288// Function:
289//    spnegoTokenGetBinary
290//
291// Parameters:
292//    [in]     hSpnegoToken   -  Initialized SPNEGO_TOKEN_HANDLE
293//    [out]    pbTokenData    -  Buffer to copy token into
294//    [in/out] pulDataLen     -  Length of pbTokenData buffer, filled out
295//                               with actual size used upon function return.
296//
297// Returns:
298//    int   Success - SPNEGO_E_SUCCESS
299//          Failure - SPNEGO API Error code
300//
301// Comments :
302//    Copies binary SPNEGO token data from hSpnegoToken into the user
303//    supplied buffer.  If pbTokenData is NULL, or the value in pulDataLen
304//    is too small, the function will return SPNEGO_E_BUFFER_TOO_SMALL and
305//    fill out pulDataLen with the minimum required buffer size.
306//
307////////////////////////////////////////////////////////////////////////////
308
309int spnegoTokenGetBinary( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pbTokenData,
310                           unsigned long * pulDataLen )
311{
312   int   nReturn = SPNEGO_E_INVALID_PARAMETER;
313   SPNEGO_TOKEN*  pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
314
315   // Check parameters - pbTokenData is optional
316   if (  IsValidSpnegoToken( pSpnegoToken ) &&
317         NULL != pulDataLen )
318   {
319
320      // Check for Buffer too small conditions
321      if ( NULL == pbTokenData ||
322            pSpnegoToken->ulBinaryDataLen > *pulDataLen )
323      {
324         *pulDataLen = pSpnegoToken->ulBinaryDataLen;
325         nReturn = SPNEGO_E_BUFFER_TOO_SMALL;
326      }
327      else
328      {
329         memcpy( pbTokenData, pSpnegoToken->pbBinaryData, pSpnegoToken->ulBinaryDataLen );
330         *pulDataLen = pSpnegoToken->ulBinaryDataLen;
331         nReturn = SPNEGO_E_SUCCESS;
332      }
333
334   }  // IF parameters OK
335
336   return nReturn;;
337}
338
339/////////////////////////////////////////////////////////////////////////////
340//
341// Function:
342//    spnegoFreeData
343//
344// Parameters:
345//    [in]     hSpnegoToken   -  Initialized SPNEGO_TOKEN_HANDLE
346//
347// Returns:
348//    void
349//
350// Comments :
351//    Frees up resources consumed by hSpnegoToken.  The supplied data
352//    pointer is invalidated by this function.
353//
354////////////////////////////////////////////////////////////////////////////
355
356void spnegoFreeData( SPNEGO_TOKEN_HANDLE hSpnegoToken )
357{
358   FreeSpnegoToken( (SPNEGO_TOKEN*) hSpnegoToken);
359   return;
360}
361
362/////////////////////////////////////////////////////////////////////////////
363//
364// Function:
365//    spnegoGetTokenType
366//
367// Parameters:
368//    [in]  hSpnegoToken      -  Initialized SPNEGO_TOKEN_HANDLE
369//    [out] piTokenType       -  Filled out with token type value.
370//
371// Returns:
372//    int   Success - SPNEGO_E_SUCCESS
373//          Failure - SPNEGO API Error code
374//
375// Comments :
376//    The function will analyze hSpnegoToken and return the appropriate
377//    type in piTokenType.
378//
379////////////////////////////////////////////////////////////////////////////
380
381int spnegoGetTokenType( SPNEGO_TOKEN_HANDLE hSpnegoToken, int * piTokenType )
382{
383   int   nReturn = SPNEGO_E_INVALID_PARAMETER;
384   SPNEGO_TOKEN*  pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
385
386   // Check parameters
387   if (  IsValidSpnegoToken( pSpnegoToken ) &&
388         NULL != piTokenType &&
389         pSpnegoToken)
390   {
391
392      // Check that the type in the structure makes sense
393      if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType ||
394            SPNEGO_TOKEN_TARG == pSpnegoToken->ucTokenType )
395      {
396         *piTokenType = pSpnegoToken->ucTokenType;
397         nReturn = SPNEGO_E_SUCCESS;
398      }
399
400   }  // IF parameters OK
401
402   return nReturn;
403}
404
405/////////////////////////////////////////////////////////////////////////////
406//
407// Function:
408//    spnegoIsMechTypeAvailable
409//
410// Parameters:
411//    [in]  hSpnegoToken      -  Initialized SPNEGO_TOKEN_HANDLE
412//    [in]  MechOID           -  MechOID to search MechTypeList for
413//    [out] piMechTypeIndex   -  Filled out with index in MechTypeList
414//                               element if MechOID is found.
415//
416// Returns:
417//    int   Success - SPNEGO_E_SUCCESS
418//          Failure - SPNEGO API Error code
419//
420// Comments :
421//    hSpnegoToken must reference a token of type NegTokenInit.  The
422//    function will search the MechTypeList element for an OID corresponding
423//    to the specified MechOID.  If one is found, the index (0 based) will
424//    be passed into the piMechTypeIndex parameter.
425//
426////////////////////////////////////////////////////////////////////////////
427
428// Returns the Initial Mech Type in the MechList element in the NegInitToken.
429int spnegoIsMechTypeAvailable( SPNEGO_TOKEN_HANDLE hSpnegoToken, SPNEGO_MECH_OID MechOID, int * piMechTypeIndex )
430{
431   int   nReturn = SPNEGO_E_INVALID_PARAMETER;
432   SPNEGO_TOKEN*  pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
433
434   // Check parameters
435   if (  IsValidSpnegoToken( pSpnegoToken ) &&
436         NULL != piMechTypeIndex &&
437         IsValidMechOid( MechOID ) &&
438         SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
439   {
440
441      // Check if MechList is available
442      if ( pSpnegoToken->aElementArray[SPNEGO_INIT_MECHTYPES_ELEMENT].iElementPresent
443            == SPNEGO_TOKEN_ELEMENT_AVAILABLE )
444      {
445         // Locate the MechOID in the list element
446         nReturn = FindMechOIDInMechList(
447                     &pSpnegoToken->aElementArray[SPNEGO_INIT_MECHTYPES_ELEMENT],
448                     MechOID, piMechTypeIndex );
449      }
450      else
451      {
452         nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
453      }
454
455   }  // IF parameters OK
456
457   return nReturn;;
458}
459
460/////////////////////////////////////////////////////////////////////////////
461//
462// Function:
463//    spnegoGetContextFlags
464//
465// Parameters:
466//    [in]  hSpnegoToken      -  Initialized SPNEGO_TOKEN_HANDLE
467//    [out] pucContextFlags   -  Filled out with ContextFlags value.
468//
469// Returns:
470//    int   Success - SPNEGO_E_SUCCESS
471//          Failure - SPNEGO API Error code
472//
473// Comments :
474//    hSpnegoToken must reference a token of type NegTokenInit.  The
475//    function will copy data from the ContextFlags element into the
476//    location pucContextFlags points to.  Note that the function will
477//    fail if the actual ContextFlags data appears invalid.
478//
479////////////////////////////////////////////////////////////////////////////
480
481int spnegoGetContextFlags( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pucContextFlags )
482{
483   int   nReturn = SPNEGO_E_INVALID_PARAMETER;
484   SPNEGO_TOKEN*  pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
485
486   // Check parameters
487   if (  IsValidSpnegoToken( pSpnegoToken ) &&
488         NULL != pucContextFlags &&
489         SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
490   {
491
492      // Check if ContextFlags is available
493      if ( pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].iElementPresent
494            == SPNEGO_TOKEN_ELEMENT_AVAILABLE )
495      {
496         // The length should be two, the value should show a 1 bit difference in the difference byte, and
497         // the value must be valid
498         if ( pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].nDatalength == SPNEGO_NEGINIT_MAXLEN_REQFLAGS &&
499               pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].pbData[0] == SPNEGO_NEGINIT_REQFLAGS_BITDIFF &&
500               IsValidContextFlags( pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].pbData[1] ) )
501         {
502            *pucContextFlags = pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].pbData[1];
503            nReturn = SPNEGO_E_SUCCESS;
504         }
505         else
506         {
507            nReturn = SPNEGO_E_INVALID_ELEMENT;
508         }
509
510      }
511      else
512      {
513         nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
514      }
515
516   }  // IF parameters OK
517
518   return nReturn;;
519}
520
521/////////////////////////////////////////////////////////////////////////////
522//
523// Function:
524//    spnegoGetNegotiationResult
525//
526// Parameters:
527//    [in]  hSpnegoToken      -  Initialized SPNEGO_TOKEN_HANDLE
528//    [out] pnegResult        -  Filled out with NegResult value.
529//
530// Returns:
531//    int   Success - SPNEGO_E_SUCCESS
532//          Failure - SPNEGO API Error code
533//
534// Comments :
535//    hSpnegoToken must reference a token of type NegTokenTarg.  The
536//    function will copy data from the NegResult element into the
537//    location pointed to by pnegResult.  Note that the function will
538//    fail if the actual NegResult data appears invalid.
539//
540////////////////////////////////////////////////////////////////////////////
541
542int spnegoGetNegotiationResult( SPNEGO_TOKEN_HANDLE hSpnegoToken, SPNEGO_NEGRESULT* pnegResult )
543{
544   int   nReturn = SPNEGO_E_INVALID_PARAMETER;
545   SPNEGO_TOKEN*  pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
546
547   // Check parameters
548   if (  IsValidSpnegoToken( pSpnegoToken ) &&
549         NULL != pnegResult &&
550         SPNEGO_TOKEN_TARG == pSpnegoToken->ucTokenType )
551   {
552
553      // Check if NegResult is available
554      if ( pSpnegoToken->aElementArray[SPNEGO_TARG_NEGRESULT_ELEMENT].iElementPresent
555            == SPNEGO_TOKEN_ELEMENT_AVAILABLE )
556      {
557         // Must be 1 byte long and a valid value
558         if ( pSpnegoToken->aElementArray[SPNEGO_TARG_NEGRESULT_ELEMENT].nDatalength == SPNEGO_NEGTARG_MAXLEN_NEGRESULT &&
559               IsValidNegResult( *pSpnegoToken->aElementArray[SPNEGO_TARG_NEGRESULT_ELEMENT].pbData ) )
560         {
561            *pnegResult = *pSpnegoToken->aElementArray[SPNEGO_TARG_NEGRESULT_ELEMENT].pbData;
562            nReturn = SPNEGO_E_SUCCESS;
563         }
564         else
565         {
566            nReturn = SPNEGO_E_INVALID_ELEMENT;
567         }
568      }
569      else
570      {
571         nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
572      }
573
574   }  // IF parameters OK
575
576   return nReturn;;
577}
578
579/////////////////////////////////////////////////////////////////////////////
580//
581// Function:
582//    spnegoGetSupportedMechType
583//
584// Parameters:
585//    [in]  hSpnegoToken      -  Initialized SPNEGO_TOKEN_HANDLE
586//    [out] pMechOID          -  Filled out with Supported MechType value.
587//
588// Returns:
589//    int   Success - SPNEGO_E_SUCCESS
590//          Failure - SPNEGO API Error code
591//
592// Comments :
593//    hSpnegoToken must reference a token of type NegTokenTarg.  The
594//    function will check the Supported MechType element, and if it
595//    corresponds to a supported MechType ( spnego_mech_oid_Kerberos_V5_Legacy
596//    or spnego_mech_oid_Kerberos_V5 ), will set the location pointed
597//    to by pMechOID equal to the appropriate value.
598//
599////////////////////////////////////////////////////////////////////////////
600
601int spnegoGetSupportedMechType( SPNEGO_TOKEN_HANDLE hSpnegoToken, SPNEGO_MECH_OID* pMechOID  )
602{
603   int   nReturn = SPNEGO_E_INVALID_PARAMETER;
604   int   nCtr = 0L;
605   long  nLength = 0L;
606   SPNEGO_TOKEN*  pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
607
608   // Check parameters
609   if (  IsValidSpnegoToken( pSpnegoToken ) &&
610         NULL != pMechOID &&
611         SPNEGO_TOKEN_TARG == pSpnegoToken->ucTokenType )
612   {
613
614      // Check if MechList is available
615      if ( pSpnegoToken->aElementArray[SPNEGO_TARG_SUPPMECH_ELEMENT].iElementPresent
616            == SPNEGO_TOKEN_ELEMENT_AVAILABLE )
617      {
618
619         for ( nCtr = 0;
620               nReturn != SPNEGO_E_SUCCESS &&
621               g_stcMechOIDList[nCtr].eMechanismOID != spnego_mech_oid_NotUsed;
622               nCtr++ )
623         {
624
625            if ( ( nReturn = ASNDerCheckOID(
626                        pSpnegoToken->aElementArray[SPNEGO_TARG_SUPPMECH_ELEMENT].pbData,
627                        nCtr,
628                        pSpnegoToken->aElementArray[SPNEGO_TARG_SUPPMECH_ELEMENT].nDatalength,
629                        &nLength ) ) == SPNEGO_E_SUCCESS )
630            {
631               *pMechOID = nCtr;
632            }
633
634         }  // For enum MechOIDs
635
636
637      }
638      else
639      {
640         nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
641      }
642
643   }  // IF parameters OK
644
645   return nReturn;;
646}
647
648/////////////////////////////////////////////////////////////////////////////
649//
650// Function:
651//    spnegoTokenGetMechToken
652//
653// Parameters:
654//    [in]     hSpnegoToken   -  Initialized SPNEGO_TOKEN_HANDLE
655//    [out]    pbTokenData    -  Buffer to copy MechToken into
656//    [in/out] pulDataLen     -  Length of pbTokenData buffer, filled out
657//                               with actual size used upon function return.
658//
659// Returns:
660//    int   Success - SPNEGO_E_SUCCESS
661//          Failure - SPNEGO API Error code
662//
663// Comments :
664//    hSpnegoToken can point to either NegTokenInit or a NegTokenTarg token.
665//    The function will copy the MechToken (the initial MechToken if
666//    NegTokenInit, the response MechToken if NegTokenTarg) from the
667//    underlying token into the buffer pointed to by pbTokenData.  If
668//    pbTokenData is NULL, or the value in pulDataLen is too small, the
669//    function will return SPNEGO_E_BUFFER_TOO_SMALL and fill out pulDataLen
670//    with the minimum required buffer size.  The token can then be passed
671//    to a GSS-API function for processing.
672//
673////////////////////////////////////////////////////////////////////////////
674
675int spnegoGetMechToken( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pbTokenData, unsigned long* pulDataLen )
676{
677   int   nReturn = SPNEGO_E_INVALID_PARAMETER;
678   SPNEGO_TOKEN*  pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
679   SPNEGO_ELEMENT*   pSpnegoElement = NULL;
680
681   // Check parameters
682   if (  IsValidSpnegoToken( pSpnegoToken ) &&
683         NULL != pulDataLen )
684   {
685
686      // Point at the proper Element
687      if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
688      {
689         pSpnegoElement = &pSpnegoToken->aElementArray[SPNEGO_INIT_MECHTOKEN_ELEMENT];
690      }
691      else
692      {
693         pSpnegoElement = &pSpnegoToken->aElementArray[SPNEGO_TARG_RESPTOKEN_ELEMENT];
694      }
695
696      // Check if MechType is available
697      if ( SPNEGO_TOKEN_ELEMENT_AVAILABLE == pSpnegoElement->iElementPresent  )
698      {
699         // Check for Buffer too small conditions
700         if ( NULL == pbTokenData ||
701               pSpnegoElement->nDatalength > *pulDataLen )
702         {
703            *pulDataLen = pSpnegoElement->nDatalength;
704            nReturn = SPNEGO_E_BUFFER_TOO_SMALL;
705         }
706         else
707         {
708            // Copy Memory
709            memcpy( pbTokenData, pSpnegoElement->pbData, pSpnegoElement->nDatalength );
710            *pulDataLen = pSpnegoElement->nDatalength;
711            nReturn = SPNEGO_E_SUCCESS;
712         }
713      }
714      else
715      {
716         nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
717      }
718
719   }  // IF parameters OK
720
721   return nReturn;;
722}
723
724/////////////////////////////////////////////////////////////////////////////
725//
726// Function:
727//    spnegoTokenGetMechListMIC
728//
729// Parameters:
730//    [in]     hSpnegoToken   -  Initialized SPNEGO_TOKEN_HANDLE
731//    [out]    pbTokenData    -  Buffer to copy MechListMIC data into
732//    [in/out] pulDataLen     -  Length of pbTokenData buffer, filled out
733//                               with actual size used upon function return.
734//
735// Returns:
736//    int   Success - SPNEGO_E_SUCCESS
737//          Failure - SPNEGO API Error code
738//
739// Comments :
740//    hSpnegoToken can point to either NegTokenInit or a NegTokenTarg token.
741//    The function will copy the MechListMIC data from the underlying token
742//    into the buffer pointed to by pbTokenData.  If pbTokenData is NULL,
743//    or the value in pulDataLen is too small, the function will return
744//    SPNEGO_E_BUFFER_TOO_SMALL and fill out pulDataLen with the minimum
745//    required buffer size.
746//
747////////////////////////////////////////////////////////////////////////////
748
749int spnegoGetMechListMIC( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pbMICData, unsigned long* pulDataLen )
750{
751   int   nReturn = SPNEGO_E_INVALID_PARAMETER;
752   SPNEGO_TOKEN*  pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
753   SPNEGO_ELEMENT*   pSpnegoElement = NULL;
754
755   // Check parameters
756   if (  IsValidSpnegoToken( pSpnegoToken ) &&
757         NULL != pulDataLen )
758   {
759
760      // Point at the proper Element
761      if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
762      {
763         pSpnegoElement = &pSpnegoToken->aElementArray[SPNEGO_INIT_MECHLISTMIC_ELEMENT];
764      }
765      else
766      {
767         pSpnegoElement = &pSpnegoToken->aElementArray[SPNEGO_TARG_MECHLISTMIC_ELEMENT];
768      }
769
770      // Check if MechType is available
771      if ( SPNEGO_TOKEN_ELEMENT_AVAILABLE == pSpnegoElement->iElementPresent  )
772      {
773         // Check for Buffer too small conditions
774         if ( NULL == pbMICData ||
775               pSpnegoElement->nDatalength > *pulDataLen )
776         {
777            *pulDataLen = pSpnegoElement->nDatalength;
778            nReturn = SPNEGO_E_BUFFER_TOO_SMALL;
779         }
780         else
781         {
782            // Copy Memory
783            memcpy( pbMICData, pSpnegoElement->pbData, pSpnegoElement->nDatalength );
784            *pulDataLen = pSpnegoElement->nDatalength;
785            nReturn = SPNEGO_E_SUCCESS;
786         }
787      }
788      else
789      {
790         nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
791      }
792
793   }  // IF parameters OK
794
795   return nReturn;;
796}
797
798