1 // Copyright 2012 Nexenta Systems, Inc. All rights reserved.
2 // Copyright (C) 2002 Microsoft Corporation
3 // All rights reserved.
5 // THIS CODE AND INFORMATION IS PROVIDED "AS IS"
6 // WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
7 // OR IMPLIED, INCLUDING BUT NOT LIMITED
8 // TO THE IMPLIED WARRANTIES OF MERCHANTIBILITY
9 // AND/OR FITNESS FOR A PARTICULAR PURPOSE.
12 // Author - Sanj Surati
14 /////////////////////////////////////////////////////////////
18 // SPNEGO Token Handler Source File
20 // Contains implementation of SPNEGO Token Handling API
21 // as defined in SPNEGO.H.
23 /////////////////////////////////////////////////////////////
31 #include "spnegoparse.h"
34 // Defined in DERPARSE.C
37 extern MECH_OID g_stcMechOIDList
[];
40 /**********************************************************************/
45 /** SPNEGO Token Handler API implementation **/
50 /**********************************************************************/
53 /////////////////////////////////////////////////////////////////////////////
56 // spnegoInitFromBinary
59 // [in] pbTokenData - Binary Token Data
60 // [in] ulLength - Length of binary Token Data
61 // [out] phSpnegoToken - SPNEGO_TOKEN_HANDLE pointer
64 // int Success - SPNEGO_E_SUCCESS
65 // Failure - SPNEGO API Error code
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().
72 ////////////////////////////////////////////////////////////////////////////
74 int spnegoInitFromBinary( unsigned char* pbTokenData
, unsigned long ulLength
, SPNEGO_TOKEN_HANDLE
* phSpnegoToken
)
76 int nReturn
= SPNEGO_E_INVALID_PARAMETER
;
77 SPNEGO_TOKEN
** ppSpnegoToken
= (SPNEGO_TOKEN
**) phSpnegoToken
;
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
82 nReturn
= InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYDATA
,
83 SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA
, pbTokenData
,
84 ulLength
, ppSpnegoToken
);
89 /////////////////////////////////////////////////////////////////////////////
92 // spnegoCreateNegTokenHint
95 // [in] pMechTypeList - List of MechTypes (OIDs) to include
96 // [in] MechTypeCnt - Length of MechTypes array
97 // [in] pbPrincipal - Principal name for MechListMIC
98 // [out] phSpnegoToken - SPNEGO_TOKEN_HANDLE pointer
101 // int Success - SPNEGO_E_SUCCESS
102 // Failure - SPNEGO API Error code
105 // Initializes a SPNEGO_TOKEN_HANDLE for a NegTokenInit type token
106 // from the supplied parameters. The token created is the "hint"
107 // used (for example) in the response to an SMB negotiate protocol.
108 // Returned data structure must be freed by calling spnegoFreeData().
110 // The "hint" tells the client what authentication methods this
111 // server supports (the ones in the MechTypeList). The Principal
112 // name historically was the server's own SPN, but recent versions
113 // of windows only supply: "not_defined_in_RFC4178@please_ignore"
114 // So if you want to be nice to your clients, provide the host SPN,
115 // otherwise provide the bogus SPN string like recent windows.
117 ////////////////////////////////////////////////////////////////////////////
119 int spnegoCreateNegTokenHint( SPNEGO_MECH_OID
*pMechTypeList
, int MechTypeCnt
,
120 unsigned char *pbPrincipal
, SPNEGO_TOKEN_HANDLE
* phSpnegoToken
)
123 long nTokenLength
= 0L;
124 long nInternalTokenLength
= 0L;
125 unsigned long ulPrincipalLen
;
126 unsigned char* pbMechListMIC
;
127 unsigned long ulMechListMICLen
;
128 unsigned char* pbTokenData
= NULL
;
129 SPNEGO_TOKEN
** ppSpnegoToken
= (SPNEGO_TOKEN
**) phSpnegoToken
;
131 if ( NULL
== ppSpnegoToken
|| NULL
== pbPrincipal
)
132 return (SPNEGO_E_INVALID_PARAMETER
);
135 * Get the actual token size
137 ulPrincipalLen
= strlen((char *)pbPrincipal
);
138 ulMechListMICLen
= ASNDerCalcElementLength( ulPrincipalLen
, NULL
);
139 nReturn
= CalculateMinSpnegoInitTokenSize(
140 0, /* ulMechTokenLen */
144 0, /* nReqFlagsAvailable */
146 &nInternalTokenLength
);
147 if ( nReturn
!= SPNEGO_E_SUCCESS
)
150 // Allocate a buffer to hold the data.
151 pbTokenData
= calloc( 1, nTokenLength
);
153 if ( NULL
== pbTokenData
)
154 return ( SPNEGO_E_OUT_OF_MEMORY
);
157 * Construct the MechListMIC
159 pbMechListMIC
= pbTokenData
+ (nTokenLength
- ulMechListMICLen
);
160 (void) ASNDerWriteElement( pbMechListMIC
, SPNEGO_NEGINIT_ELEMENT_MECHTYPES
,
161 GENERALSTR
, pbPrincipal
, ulPrincipalLen
);
163 // Now write the token
164 nReturn
= CreateSpnegoInitToken(
167 0, /* ContextFlags */
168 NULL
, 0, /* MechToken, len */
173 nInternalTokenLength
);
174 if ( nReturn
!= SPNEGO_E_SUCCESS
) {
179 // This will copy our allocated pointer, and ensure that the sructure cleans
181 nReturn
= InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYPTR
,
182 SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA
,
183 pbTokenData
, nTokenLength
, ppSpnegoToken
);
185 // Cleanup on failure
186 if ( nReturn
!= SPNEGO_E_SUCCESS
) {
191 return (SPNEGO_E_SUCCESS
);
194 /////////////////////////////////////////////////////////////////////////////
197 // spnegoCreateNegTokenInit
200 // [in] MechType - MechType to specify in MechTypeList element
201 // [in] ucContextFlags - Context Flags element value
202 // [in] pbMechToken - Pointer to binary MechToken Data
203 // [in] ulMechTokenLen - Length of MechToken Data
204 // [in] pbMechListMIC - Pointer to binary MechListMIC Data
205 // [in] ulMechListMICLen - Length of MechListMIC Data
206 // [out] phSpnegoToken - SPNEGO_TOKEN_HANDLE pointer
209 // int Success - SPNEGO_E_SUCCESS
210 // Failure - SPNEGO API Error code
213 // Initializes a SPNEGO_TOKEN_HANDLE for a NegTokenInit type
214 // from the supplied parameters. ucContextFlags may be 0 or must be
215 // a valid flag combination. MechToken data can be NULL - if not, it
216 // must correspond to the MechType. MechListMIC can also be NULL.
217 // Returned data structure must be freed by calling spnegoFreeData().
219 ////////////////////////////////////////////////////////////////////////////
221 int spnegoCreateNegTokenInit( SPNEGO_MECH_OID MechType
,
222 unsigned char ucContextFlags
, unsigned char* pbMechToken
,
223 unsigned long ulMechTokenLen
, unsigned char* pbMechListMIC
,
224 unsigned long ulMechListMICLen
, SPNEGO_TOKEN_HANDLE
* phSpnegoToken
)
226 int nReturn
= SPNEGO_E_INVALID_PARAMETER
;
227 long nTokenLength
= 0L;
228 long nInternalTokenLength
= 0L;
229 unsigned char* pbTokenData
= NULL
;
230 SPNEGO_TOKEN
** ppSpnegoToken
= (SPNEGO_TOKEN
**) phSpnegoToken
;
232 if ( NULL
!= ppSpnegoToken
&&
233 IsValidMechOid( MechType
) &&
234 IsValidContextFlags( ucContextFlags
) )
236 // Get the actual token size
238 if ( ( nReturn
= CalculateMinSpnegoInitTokenSize( ulMechTokenLen
, ulMechListMICLen
,
239 &MechType
, 1, ( ucContextFlags
!= 0L ),
240 &nTokenLength
, &nInternalTokenLength
) )
241 == SPNEGO_E_SUCCESS
)
243 // Allocate a buffer to hold the data.
244 pbTokenData
= calloc( 1, nTokenLength
);
246 if ( NULL
!= pbTokenData
)
249 // Now write the token
250 if ( ( nReturn
= CreateSpnegoInitToken( &MechType
, 1,
251 ucContextFlags
, pbMechToken
,
252 ulMechTokenLen
, pbMechListMIC
,
253 ulMechListMICLen
, pbTokenData
,
254 nTokenLength
, nInternalTokenLength
) )
255 == SPNEGO_E_SUCCESS
)
258 // This will copy our allocated pointer, and ensure that the sructure cleans
260 nReturn
= InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYPTR
,
261 SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA
,
262 pbTokenData
, nTokenLength
, ppSpnegoToken
);
266 // Cleanup on failure
267 if ( SPNEGO_E_SUCCESS
!= nReturn
)
272 } // IF alloc succeeded
275 nReturn
= SPNEGO_E_OUT_OF_MEMORY
;
278 } // If calculated token size
280 } // IF Valid Parameters
285 /////////////////////////////////////////////////////////////////////////////
288 // spnegoCreateNegTokenTarg
291 // [in] MechType - MechType to specify in supported MechType element
292 // [in] spnegoNegResult - NegResult value
293 // [in] pbMechToken - Pointer to response MechToken Data
294 // [in] ulMechTokenLen - Length of MechToken Data
295 // [in] pbMechListMIC - Pointer to binary MechListMIC Data
296 // [in] ulMechListMICLen - Length of MechListMIC Data
297 // [out] phSpnegoToken - SPNEGO_TOKEN_HANDLE pointer
300 // int Success - SPNEGO_E_SUCCESS
301 // Failure - SPNEGO API Error code
304 // Initializes a SPNEGO_TOKEN_HANDLE for a NegTokenTarg type
305 // from the supplied parameters. MechToken data can be NULL - if not,
306 // it must correspond to the MechType. MechListMIC can also be NULL.
307 // Returned data structure must be freed by calling spnegoFreeData().
309 ////////////////////////////////////////////////////////////////////////////
311 int spnegoCreateNegTokenTarg( SPNEGO_MECH_OID MechType
,
312 SPNEGO_NEGRESULT spnegoNegResult
, unsigned char* pbMechToken
,
313 unsigned long ulMechTokenLen
, unsigned char* pbMechListMIC
,
314 unsigned long ulMechListMICLen
, SPNEGO_TOKEN_HANDLE
* phSpnegoToken
)
316 int nReturn
= SPNEGO_E_INVALID_PARAMETER
;
317 long nTokenLength
= 0L;
318 long nInternalTokenLength
= 0L;
319 unsigned char* pbTokenData
= NULL
;
320 SPNEGO_TOKEN
** ppSpnegoToken
= (SPNEGO_TOKEN
**) phSpnegoToken
;
323 // spnego_mech_oid_NotUsed and spnego_negresult_NotUsed
324 // are okay here, however a valid MechOid is required
325 // if spnego_negresult_success or spnego_negresult_incomplete
329 if ( NULL
!= ppSpnegoToken
&&
331 ( IsValidMechOid( MechType
) ||
332 spnego_mech_oid_NotUsed
== MechType
) &&
334 ( IsValidNegResult( spnegoNegResult
) ||
335 spnego_negresult_NotUsed
== spnegoNegResult
) )
338 // Get the actual token size
340 if ( ( nReturn
= CalculateMinSpnegoTargTokenSize( MechType
, spnegoNegResult
, ulMechTokenLen
,
341 ulMechListMICLen
, &nTokenLength
,
342 &nInternalTokenLength
) )
343 == SPNEGO_E_SUCCESS
)
345 // Allocate a buffer to hold the data.
346 pbTokenData
= calloc( 1, nTokenLength
);
348 if ( NULL
!= pbTokenData
)
351 // Now write the token
352 if ( ( nReturn
= CreateSpnegoTargToken( MechType
,
353 spnegoNegResult
, pbMechToken
,
354 ulMechTokenLen
, pbMechListMIC
,
355 ulMechListMICLen
, pbTokenData
,
356 nTokenLength
, nInternalTokenLength
) )
357 == SPNEGO_E_SUCCESS
)
360 // This will copy our allocated pointer, and ensure that the sructure cleans
362 nReturn
= InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYPTR
,
363 SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA
,
364 pbTokenData
, nTokenLength
, ppSpnegoToken
);
368 // Cleanup on failure
369 if ( SPNEGO_E_SUCCESS
!= nReturn
)
374 } // IF alloc succeeded
377 nReturn
= SPNEGO_E_OUT_OF_MEMORY
;
380 } // If calculated token size
382 } // IF Valid Parameters
387 /////////////////////////////////////////////////////////////////////////////
390 // spnegoTokenGetBinary
393 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
394 // [out] pbTokenData - Buffer to copy token into
395 // [in/out] pulDataLen - Length of pbTokenData buffer, filled out
396 // with actual size used upon function return.
399 // int Success - SPNEGO_E_SUCCESS
400 // Failure - SPNEGO API Error code
403 // Copies binary SPNEGO token data from hSpnegoToken into the user
404 // supplied buffer. If pbTokenData is NULL, or the value in pulDataLen
405 // is too small, the function will return SPNEGO_E_BUFFER_TOO_SMALL and
406 // fill out pulDataLen with the minimum required buffer size.
408 ////////////////////////////////////////////////////////////////////////////
410 int spnegoTokenGetBinary( SPNEGO_TOKEN_HANDLE hSpnegoToken
, unsigned char* pbTokenData
,
411 unsigned long * pulDataLen
)
413 int nReturn
= SPNEGO_E_INVALID_PARAMETER
;
414 SPNEGO_TOKEN
* pSpnegoToken
= (SPNEGO_TOKEN
*) hSpnegoToken
;
416 // Check parameters - pbTokenData is optional
417 if ( IsValidSpnegoToken( pSpnegoToken
) &&
421 // Check for Buffer too small conditions
422 if ( NULL
== pbTokenData
||
423 pSpnegoToken
->ulBinaryDataLen
> *pulDataLen
)
425 *pulDataLen
= pSpnegoToken
->ulBinaryDataLen
;
426 nReturn
= SPNEGO_E_BUFFER_TOO_SMALL
;
430 memcpy( pbTokenData
, pSpnegoToken
->pbBinaryData
, pSpnegoToken
->ulBinaryDataLen
);
431 *pulDataLen
= pSpnegoToken
->ulBinaryDataLen
;
432 nReturn
= SPNEGO_E_SUCCESS
;
435 } // IF parameters OK
440 /////////////////////////////////////////////////////////////////////////////
446 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
452 // Frees up resources consumed by hSpnegoToken. The supplied data
453 // pointer is invalidated by this function.
455 ////////////////////////////////////////////////////////////////////////////
457 void spnegoFreeData( SPNEGO_TOKEN_HANDLE hSpnegoToken
)
459 FreeSpnegoToken( (SPNEGO_TOKEN
*) hSpnegoToken
);
463 /////////////////////////////////////////////////////////////////////////////
466 // spnegoGetTokenType
469 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
470 // [out] piTokenType - Filled out with token type value.
473 // int Success - SPNEGO_E_SUCCESS
474 // Failure - SPNEGO API Error code
477 // The function will analyze hSpnegoToken and return the appropriate
478 // type in piTokenType.
480 ////////////////////////////////////////////////////////////////////////////
482 int spnegoGetTokenType( SPNEGO_TOKEN_HANDLE hSpnegoToken
, int * piTokenType
)
484 int nReturn
= SPNEGO_E_INVALID_PARAMETER
;
485 SPNEGO_TOKEN
* pSpnegoToken
= (SPNEGO_TOKEN
*) hSpnegoToken
;
488 if ( IsValidSpnegoToken( pSpnegoToken
) &&
489 NULL
!= piTokenType
&&
493 // Check that the type in the structure makes sense
494 if ( SPNEGO_TOKEN_INIT
== pSpnegoToken
->ucTokenType
||
495 SPNEGO_TOKEN_TARG
== pSpnegoToken
->ucTokenType
)
497 *piTokenType
= pSpnegoToken
->ucTokenType
;
498 nReturn
= SPNEGO_E_SUCCESS
;
501 } // IF parameters OK
506 /////////////////////////////////////////////////////////////////////////////
509 // spnegoIsMechTypeAvailable
512 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
513 // [in] MechOID - MechOID to search MechTypeList for
514 // [out] piMechTypeIndex - Filled out with index in MechTypeList
515 // element if MechOID is found.
518 // int Success - SPNEGO_E_SUCCESS
519 // Failure - SPNEGO API Error code
522 // hSpnegoToken must reference a token of type NegTokenInit. The
523 // function will search the MechTypeList element for an OID corresponding
524 // to the specified MechOID. If one is found, the index (0 based) will
525 // be passed into the piMechTypeIndex parameter.
527 ////////////////////////////////////////////////////////////////////////////
529 // Returns the Initial Mech Type in the MechList element in the NegInitToken.
530 int spnegoIsMechTypeAvailable( SPNEGO_TOKEN_HANDLE hSpnegoToken
, SPNEGO_MECH_OID MechOID
, int * piMechTypeIndex
)
532 int nReturn
= SPNEGO_E_INVALID_PARAMETER
;
533 SPNEGO_TOKEN
* pSpnegoToken
= (SPNEGO_TOKEN
*) hSpnegoToken
;
536 if ( IsValidSpnegoToken( pSpnegoToken
) &&
537 NULL
!= piMechTypeIndex
&&
538 IsValidMechOid( MechOID
) &&
539 SPNEGO_TOKEN_INIT
== pSpnegoToken
->ucTokenType
)
542 // Check if MechList is available
543 if ( pSpnegoToken
->aElementArray
[SPNEGO_INIT_MECHTYPES_ELEMENT
].iElementPresent
544 == SPNEGO_TOKEN_ELEMENT_AVAILABLE
)
546 // Locate the MechOID in the list element
547 nReturn
= FindMechOIDInMechList(
548 &pSpnegoToken
->aElementArray
[SPNEGO_INIT_MECHTYPES_ELEMENT
],
549 MechOID
, piMechTypeIndex
);
553 nReturn
= SPNEGO_E_ELEMENT_UNAVAILABLE
;
556 } // IF parameters OK
561 /////////////////////////////////////////////////////////////////////////////
564 // spnegoGetContextFlags
567 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
568 // [out] pucContextFlags - Filled out with ContextFlags value.
571 // int Success - SPNEGO_E_SUCCESS
572 // Failure - SPNEGO API Error code
575 // hSpnegoToken must reference a token of type NegTokenInit. The
576 // function will copy data from the ContextFlags element into the
577 // location pucContextFlags points to. Note that the function will
578 // fail if the actual ContextFlags data appears invalid.
580 ////////////////////////////////////////////////////////////////////////////
582 int spnegoGetContextFlags( SPNEGO_TOKEN_HANDLE hSpnegoToken
, unsigned char* pucContextFlags
)
584 int nReturn
= SPNEGO_E_INVALID_PARAMETER
;
585 SPNEGO_TOKEN
* pSpnegoToken
= (SPNEGO_TOKEN
*) hSpnegoToken
;
588 if ( IsValidSpnegoToken( pSpnegoToken
) &&
589 NULL
!= pucContextFlags
&&
590 SPNEGO_TOKEN_INIT
== pSpnegoToken
->ucTokenType
)
593 // Check if ContextFlags is available
594 if ( pSpnegoToken
->aElementArray
[SPNEGO_INIT_REQFLAGS_ELEMENT
].iElementPresent
595 == SPNEGO_TOKEN_ELEMENT_AVAILABLE
)
597 // The length should be two, the value should show a 1 bit difference in the difference byte, and
598 // the value must be valid
599 if ( pSpnegoToken
->aElementArray
[SPNEGO_INIT_REQFLAGS_ELEMENT
].nDatalength
== SPNEGO_NEGINIT_MAXLEN_REQFLAGS
&&
600 pSpnegoToken
->aElementArray
[SPNEGO_INIT_REQFLAGS_ELEMENT
].pbData
[0] == SPNEGO_NEGINIT_REQFLAGS_BITDIFF
&&
601 IsValidContextFlags( pSpnegoToken
->aElementArray
[SPNEGO_INIT_REQFLAGS_ELEMENT
].pbData
[1] ) )
603 *pucContextFlags
= pSpnegoToken
->aElementArray
[SPNEGO_INIT_REQFLAGS_ELEMENT
].pbData
[1];
604 nReturn
= SPNEGO_E_SUCCESS
;
608 nReturn
= SPNEGO_E_INVALID_ELEMENT
;
614 nReturn
= SPNEGO_E_ELEMENT_UNAVAILABLE
;
617 } // IF parameters OK
622 /////////////////////////////////////////////////////////////////////////////
625 // spnegoGetNegotiationResult
628 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
629 // [out] pnegResult - Filled out with NegResult value.
632 // int Success - SPNEGO_E_SUCCESS
633 // Failure - SPNEGO API Error code
636 // hSpnegoToken must reference a token of type NegTokenTarg. The
637 // function will copy data from the NegResult element into the
638 // location pointed to by pnegResult. Note that the function will
639 // fail if the actual NegResult data appears invalid.
641 ////////////////////////////////////////////////////////////////////////////
643 int spnegoGetNegotiationResult( SPNEGO_TOKEN_HANDLE hSpnegoToken
, SPNEGO_NEGRESULT
* pnegResult
)
645 int nReturn
= SPNEGO_E_INVALID_PARAMETER
;
646 SPNEGO_TOKEN
* pSpnegoToken
= (SPNEGO_TOKEN
*) hSpnegoToken
;
649 if ( IsValidSpnegoToken( pSpnegoToken
) &&
650 NULL
!= pnegResult
&&
651 SPNEGO_TOKEN_TARG
== pSpnegoToken
->ucTokenType
)
654 // Check if NegResult is available
655 if ( pSpnegoToken
->aElementArray
[SPNEGO_TARG_NEGRESULT_ELEMENT
].iElementPresent
656 == SPNEGO_TOKEN_ELEMENT_AVAILABLE
)
658 // Must be 1 byte long and a valid value
659 if ( pSpnegoToken
->aElementArray
[SPNEGO_TARG_NEGRESULT_ELEMENT
].nDatalength
== SPNEGO_NEGTARG_MAXLEN_NEGRESULT
&&
660 IsValidNegResult( *pSpnegoToken
->aElementArray
[SPNEGO_TARG_NEGRESULT_ELEMENT
].pbData
) )
662 *pnegResult
= *pSpnegoToken
->aElementArray
[SPNEGO_TARG_NEGRESULT_ELEMENT
].pbData
;
663 nReturn
= SPNEGO_E_SUCCESS
;
667 nReturn
= SPNEGO_E_INVALID_ELEMENT
;
672 nReturn
= SPNEGO_E_ELEMENT_UNAVAILABLE
;
675 } // IF parameters OK
680 /////////////////////////////////////////////////////////////////////////////
683 // spnegoGetSupportedMechType
686 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
687 // [out] pMechOID - Filled out with Supported MechType value.
690 // int Success - SPNEGO_E_SUCCESS
691 // Failure - SPNEGO API Error code
694 // hSpnegoToken must reference a token of type NegTokenTarg. The
695 // function will check the Supported MechType element, and if it
696 // corresponds to a supported MechType ( spnego_mech_oid_Kerberos_V5_Legacy
697 // or spnego_mech_oid_Kerberos_V5 ), will set the location pointed
698 // to by pMechOID equal to the appropriate value.
700 ////////////////////////////////////////////////////////////////////////////
702 int spnegoGetSupportedMechType( SPNEGO_TOKEN_HANDLE hSpnegoToken
, SPNEGO_MECH_OID
* pMechOID
)
704 int nReturn
= SPNEGO_E_INVALID_PARAMETER
;
707 SPNEGO_TOKEN
* pSpnegoToken
= (SPNEGO_TOKEN
*) hSpnegoToken
;
710 if ( IsValidSpnegoToken( pSpnegoToken
) &&
712 SPNEGO_TOKEN_TARG
== pSpnegoToken
->ucTokenType
)
715 // Check if MechList is available
716 if ( pSpnegoToken
->aElementArray
[SPNEGO_TARG_SUPPMECH_ELEMENT
].iElementPresent
717 == SPNEGO_TOKEN_ELEMENT_AVAILABLE
)
721 nReturn
!= SPNEGO_E_SUCCESS
&&
722 g_stcMechOIDList
[nCtr
].eMechanismOID
!= spnego_mech_oid_NotUsed
;
726 if ( ( nReturn
= ASNDerCheckOID(
727 pSpnegoToken
->aElementArray
[SPNEGO_TARG_SUPPMECH_ELEMENT
].pbData
,
729 pSpnegoToken
->aElementArray
[SPNEGO_TARG_SUPPMECH_ELEMENT
].nDatalength
,
730 &nLength
) ) == SPNEGO_E_SUCCESS
)
735 } // For enum MechOIDs
741 nReturn
= SPNEGO_E_ELEMENT_UNAVAILABLE
;
744 } // IF parameters OK
749 /////////////////////////////////////////////////////////////////////////////
752 // spnegoTokenGetMechToken
755 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
756 // [out] pbTokenData - Buffer to copy MechToken into
757 // [in/out] pulDataLen - Length of pbTokenData buffer, filled out
758 // with actual size used upon function return.
761 // int Success - SPNEGO_E_SUCCESS
762 // Failure - SPNEGO API Error code
765 // hSpnegoToken can point to either NegTokenInit or a NegTokenTarg token.
766 // The function will copy the MechToken (the initial MechToken if
767 // NegTokenInit, the response MechToken if NegTokenTarg) from the
768 // underlying token into the buffer pointed to by pbTokenData. If
769 // pbTokenData is NULL, or the value in pulDataLen is too small, the
770 // function will return SPNEGO_E_BUFFER_TOO_SMALL and fill out pulDataLen
771 // with the minimum required buffer size. The token can then be passed
772 // to a GSS-API function for processing.
774 ////////////////////////////////////////////////////////////////////////////
776 int spnegoGetMechToken( SPNEGO_TOKEN_HANDLE hSpnegoToken
, unsigned char* pbTokenData
, unsigned long* pulDataLen
)
778 int nReturn
= SPNEGO_E_INVALID_PARAMETER
;
779 SPNEGO_TOKEN
* pSpnegoToken
= (SPNEGO_TOKEN
*) hSpnegoToken
;
780 SPNEGO_ELEMENT
* pSpnegoElement
= NULL
;
783 if ( IsValidSpnegoToken( pSpnegoToken
) &&
787 // Point at the proper Element
788 if ( SPNEGO_TOKEN_INIT
== pSpnegoToken
->ucTokenType
)
790 pSpnegoElement
= &pSpnegoToken
->aElementArray
[SPNEGO_INIT_MECHTOKEN_ELEMENT
];
794 pSpnegoElement
= &pSpnegoToken
->aElementArray
[SPNEGO_TARG_RESPTOKEN_ELEMENT
];
797 // Check if MechType is available
798 if ( SPNEGO_TOKEN_ELEMENT_AVAILABLE
== pSpnegoElement
->iElementPresent
)
800 // Check for Buffer too small conditions
801 if ( NULL
== pbTokenData
||
802 pSpnegoElement
->nDatalength
> *pulDataLen
)
804 *pulDataLen
= pSpnegoElement
->nDatalength
;
805 nReturn
= SPNEGO_E_BUFFER_TOO_SMALL
;
810 memcpy( pbTokenData
, pSpnegoElement
->pbData
, pSpnegoElement
->nDatalength
);
811 *pulDataLen
= pSpnegoElement
->nDatalength
;
812 nReturn
= SPNEGO_E_SUCCESS
;
817 nReturn
= SPNEGO_E_ELEMENT_UNAVAILABLE
;
820 } // IF parameters OK
825 /////////////////////////////////////////////////////////////////////////////
828 // spnegoTokenGetMechListMIC
831 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
832 // [out] pbTokenData - Buffer to copy MechListMIC data into
833 // [in/out] pulDataLen - Length of pbTokenData buffer, filled out
834 // with actual size used upon function return.
837 // int Success - SPNEGO_E_SUCCESS
838 // Failure - SPNEGO API Error code
841 // hSpnegoToken can point to either NegTokenInit or a NegTokenTarg token.
842 // The function will copy the MechListMIC data from the underlying token
843 // into the buffer pointed to by pbTokenData. If pbTokenData is NULL,
844 // or the value in pulDataLen is too small, the function will return
845 // SPNEGO_E_BUFFER_TOO_SMALL and fill out pulDataLen with the minimum
846 // required buffer size.
848 ////////////////////////////////////////////////////////////////////////////
850 int spnegoGetMechListMIC( SPNEGO_TOKEN_HANDLE hSpnegoToken
, unsigned char* pbMICData
, unsigned long* pulDataLen
)
852 int nReturn
= SPNEGO_E_INVALID_PARAMETER
;
853 SPNEGO_TOKEN
* pSpnegoToken
= (SPNEGO_TOKEN
*) hSpnegoToken
;
854 SPNEGO_ELEMENT
* pSpnegoElement
= NULL
;
857 if ( IsValidSpnegoToken( pSpnegoToken
) &&
861 // Point at the proper Element
862 if ( SPNEGO_TOKEN_INIT
== pSpnegoToken
->ucTokenType
)
864 pSpnegoElement
= &pSpnegoToken
->aElementArray
[SPNEGO_INIT_MECHLISTMIC_ELEMENT
];
868 pSpnegoElement
= &pSpnegoToken
->aElementArray
[SPNEGO_TARG_MECHLISTMIC_ELEMENT
];
871 // Check if MechType is available
872 if ( SPNEGO_TOKEN_ELEMENT_AVAILABLE
== pSpnegoElement
->iElementPresent
)
874 // Check for Buffer too small conditions
875 if ( NULL
== pbMICData
||
876 pSpnegoElement
->nDatalength
> *pulDataLen
)
878 *pulDataLen
= pSpnegoElement
->nDatalength
;
879 nReturn
= SPNEGO_E_BUFFER_TOO_SMALL
;
884 memcpy( pbMICData
, pSpnegoElement
->pbData
, pSpnegoElement
->nDatalength
);
885 *pulDataLen
= pSpnegoElement
->nDatalength
;
886 nReturn
= SPNEGO_E_SUCCESS
;
891 nReturn
= SPNEGO_E_ELEMENT_UNAVAILABLE
;
894 } // IF parameters OK