ses: SUN plugin doesn't actually need libnvfru
[unleashed.git] / usr / src / lib / libsmbfs / smb / spnego.c
bloba15303da30d1027e67e85d4b653f5c6d80f50c62
1 // Copyright 2012 Nexenta Systems, Inc. All rights reserved.
2 // Copyright (C) 2002 Microsoft Corporation
3 // All rights reserved.
4 //
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.
11 // Date - 10/08/2002
12 // Author - Sanj Surati
14 /////////////////////////////////////////////////////////////
16 // SPNEGO.C
18 // SPNEGO Token Handler Source File
20 // Contains implementation of SPNEGO Token Handling API
21 // as defined in SPNEGO.H.
23 /////////////////////////////////////////////////////////////
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <memory.h>
29 #include "spnego.h"
30 #include "derparse.h"
31 #include "spnegoparse.h"
34 // Defined in DERPARSE.C
37 extern MECH_OID g_stcMechOIDList [];
40 /**********************************************************************/
41 /** **/
42 /** **/
43 /** **/
44 /** **/
45 /** SPNEGO Token Handler API implementation **/
46 /** **/
47 /** **/
48 /** **/
49 /** **/
50 /**********************************************************************/
53 /////////////////////////////////////////////////////////////////////////////
55 // Function:
56 // spnegoInitFromBinary
58 // Parameters:
59 // [in] pbTokenData - Binary Token Data
60 // [in] ulLength - Length of binary Token Data
61 // [out] phSpnegoToken - SPNEGO_TOKEN_HANDLE pointer
63 // Returns:
64 // int Success - SPNEGO_E_SUCCESS
65 // Failure - SPNEGO API Error code
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().
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
81 // freed.
82 nReturn = InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYDATA,
83 SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA, pbTokenData,
84 ulLength, ppSpnegoToken );
86 return nReturn;
89 /////////////////////////////////////////////////////////////////////////////
91 // Function:
92 // spnegoCreateNegTokenHint
94 // Parameters:
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
100 // Returns:
101 // int Success - SPNEGO_E_SUCCESS
102 // Failure - SPNEGO API Error code
104 // Comments :
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 )
122 int nReturn;
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 */
141 ulMechListMICLen,
142 pMechTypeList,
143 MechTypeCnt,
144 0, /* nReqFlagsAvailable */
145 &nTokenLength,
146 &nInternalTokenLength );
147 if ( nReturn != SPNEGO_E_SUCCESS )
148 return (nReturn);
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(
165 pMechTypeList,
166 MechTypeCnt,
167 0, /* ContextFlags */
168 NULL, 0, /* MechToken, len */
169 pbMechListMIC,
170 ulMechListMICLen,
171 pbTokenData,
172 nTokenLength,
173 nInternalTokenLength );
174 if ( nReturn != SPNEGO_E_SUCCESS ) {
175 free( pbTokenData );
176 return (nReturn);
179 // This will copy our allocated pointer, and ensure that the sructure cleans
180 // up the data later
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 ) {
187 free( pbTokenData );
188 return (nReturn);
191 return (SPNEGO_E_SUCCESS);
194 /////////////////////////////////////////////////////////////////////////////
196 // Function:
197 // spnegoCreateNegTokenInit
199 // Parameters:
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
208 // Returns:
209 // int Success - SPNEGO_E_SUCCESS
210 // Failure - SPNEGO API Error code
212 // Comments :
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
259 // up the data later
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 )
269 free( pbTokenData );
272 } // IF alloc succeeded
273 else
275 nReturn = SPNEGO_E_OUT_OF_MEMORY;
278 } // If calculated token size
280 } // IF Valid Parameters
282 return nReturn;
285 /////////////////////////////////////////////////////////////////////////////
287 // Function:
288 // spnegoCreateNegTokenTarg
290 // Parameters:
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
299 // Returns:
300 // int Success - SPNEGO_E_SUCCESS
301 // Failure - SPNEGO API Error code
303 // Comments :
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
326 // is specified.
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
361 // up the data later
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 )
371 free( pbTokenData );
374 } // IF alloc succeeded
375 else
377 nReturn = SPNEGO_E_OUT_OF_MEMORY;
380 } // If calculated token size
382 } // IF Valid Parameters
384 return nReturn;
387 /////////////////////////////////////////////////////////////////////////////
389 // Function:
390 // spnegoTokenGetBinary
392 // Parameters:
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.
398 // Returns:
399 // int Success - SPNEGO_E_SUCCESS
400 // Failure - SPNEGO API Error code
402 // Comments :
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 ) &&
418 NULL != pulDataLen )
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;
428 else
430 memcpy( pbTokenData, pSpnegoToken->pbBinaryData, pSpnegoToken->ulBinaryDataLen );
431 *pulDataLen = pSpnegoToken->ulBinaryDataLen;
432 nReturn = SPNEGO_E_SUCCESS;
435 } // IF parameters OK
437 return nReturn;;
440 /////////////////////////////////////////////////////////////////////////////
442 // Function:
443 // spnegoFreeData
445 // Parameters:
446 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
448 // Returns:
449 // void
451 // Comments :
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);
460 return;
463 /////////////////////////////////////////////////////////////////////////////
465 // Function:
466 // spnegoGetTokenType
468 // Parameters:
469 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
470 // [out] piTokenType - Filled out with token type value.
472 // Returns:
473 // int Success - SPNEGO_E_SUCCESS
474 // Failure - SPNEGO API Error code
476 // Comments :
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;
487 // Check parameters
488 if ( IsValidSpnegoToken( pSpnegoToken ) &&
489 NULL != piTokenType &&
490 pSpnegoToken)
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
503 return nReturn;
506 /////////////////////////////////////////////////////////////////////////////
508 // Function:
509 // spnegoIsMechTypeAvailable
511 // Parameters:
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.
517 // Returns:
518 // int Success - SPNEGO_E_SUCCESS
519 // Failure - SPNEGO API Error code
521 // Comments :
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;
535 // Check parameters
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 );
551 else
553 nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
556 } // IF parameters OK
558 return nReturn;;
561 /////////////////////////////////////////////////////////////////////////////
563 // Function:
564 // spnegoGetContextFlags
566 // Parameters:
567 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
568 // [out] pucContextFlags - Filled out with ContextFlags value.
570 // Returns:
571 // int Success - SPNEGO_E_SUCCESS
572 // Failure - SPNEGO API Error code
574 // Comments :
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;
587 // Check parameters
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;
606 else
608 nReturn = SPNEGO_E_INVALID_ELEMENT;
612 else
614 nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
617 } // IF parameters OK
619 return nReturn;;
622 /////////////////////////////////////////////////////////////////////////////
624 // Function:
625 // spnegoGetNegotiationResult
627 // Parameters:
628 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
629 // [out] pnegResult - Filled out with NegResult value.
631 // Returns:
632 // int Success - SPNEGO_E_SUCCESS
633 // Failure - SPNEGO API Error code
635 // Comments :
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;
648 // Check parameters
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;
665 else
667 nReturn = SPNEGO_E_INVALID_ELEMENT;
670 else
672 nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
675 } // IF parameters OK
677 return nReturn;;
680 /////////////////////////////////////////////////////////////////////////////
682 // Function:
683 // spnegoGetSupportedMechType
685 // Parameters:
686 // [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
687 // [out] pMechOID - Filled out with Supported MechType value.
689 // Returns:
690 // int Success - SPNEGO_E_SUCCESS
691 // Failure - SPNEGO API Error code
693 // Comments :
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;
705 int nCtr = 0L;
706 long nLength = 0L;
707 SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
709 // Check parameters
710 if ( IsValidSpnegoToken( pSpnegoToken ) &&
711 NULL != pMechOID &&
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 )
720 for ( nCtr = 0;
721 nReturn != SPNEGO_E_SUCCESS &&
722 g_stcMechOIDList[nCtr].eMechanismOID != spnego_mech_oid_NotUsed;
723 nCtr++ )
726 if ( ( nReturn = ASNDerCheckOID(
727 pSpnegoToken->aElementArray[SPNEGO_TARG_SUPPMECH_ELEMENT].pbData,
728 nCtr,
729 pSpnegoToken->aElementArray[SPNEGO_TARG_SUPPMECH_ELEMENT].nDatalength,
730 &nLength ) ) == SPNEGO_E_SUCCESS )
732 *pMechOID = nCtr;
735 } // For enum MechOIDs
739 else
741 nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
744 } // IF parameters OK
746 return nReturn;;
749 /////////////////////////////////////////////////////////////////////////////
751 // Function:
752 // spnegoTokenGetMechToken
754 // Parameters:
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.
760 // Returns:
761 // int Success - SPNEGO_E_SUCCESS
762 // Failure - SPNEGO API Error code
764 // Comments :
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;
782 // Check parameters
783 if ( IsValidSpnegoToken( pSpnegoToken ) &&
784 NULL != pulDataLen )
787 // Point at the proper Element
788 if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
790 pSpnegoElement = &pSpnegoToken->aElementArray[SPNEGO_INIT_MECHTOKEN_ELEMENT];
792 else
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;
807 else
809 // Copy Memory
810 memcpy( pbTokenData, pSpnegoElement->pbData, pSpnegoElement->nDatalength );
811 *pulDataLen = pSpnegoElement->nDatalength;
812 nReturn = SPNEGO_E_SUCCESS;
815 else
817 nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
820 } // IF parameters OK
822 return nReturn;;
825 /////////////////////////////////////////////////////////////////////////////
827 // Function:
828 // spnegoTokenGetMechListMIC
830 // Parameters:
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.
836 // Returns:
837 // int Success - SPNEGO_E_SUCCESS
838 // Failure - SPNEGO API Error code
840 // Comments :
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;
856 // Check parameters
857 if ( IsValidSpnegoToken( pSpnegoToken ) &&
858 NULL != pulDataLen )
861 // Point at the proper Element
862 if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
864 pSpnegoElement = &pSpnegoToken->aElementArray[SPNEGO_INIT_MECHLISTMIC_ELEMENT];
866 else
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;
881 else
883 // Copy Memory
884 memcpy( pbMICData, pSpnegoElement->pbData, pSpnegoElement->nDatalength );
885 *pulDataLen = pSpnegoElement->nDatalength;
886 nReturn = SPNEGO_E_SUCCESS;
889 else
891 nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
894 } // IF parameters OK
896 return nReturn;;