xref: /illumos-gate/usr/src/lib/libsmbfs/smb/spnego.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 
37 extern 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 
74 int 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 
116 int 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 
206 int 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 
309 int 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 
356 void 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 
381 int 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.
429 int 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 
481 int 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 
542 int 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 
601 int 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 
675 int 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 
749 int 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