summaryrefslogtreecommitdiff
path: root/usr/src/lib/libsmbfs/smb/spnego.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libsmbfs/smb/spnego.c')
-rw-r--r--usr/src/lib/libsmbfs/smb/spnego.c797
1 files changed, 797 insertions, 0 deletions
diff --git a/usr/src/lib/libsmbfs/smb/spnego.c b/usr/src/lib/libsmbfs/smb/spnego.c
new file mode 100644
index 0000000000..3e300cd606
--- /dev/null
+++ b/usr/src/lib/libsmbfs/smb/spnego.c
@@ -0,0 +1,797 @@
+// Copyright (C) 2002 Microsoft Corporation
+// All rights reserved.
+//
+// THIS CODE AND INFORMATION IS PROVIDED "AS IS"
+// WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+// OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE IMPLIED WARRANTIES OF MERCHANTIBILITY
+// AND/OR FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Date - 10/08/2002
+// Author - Sanj Surati
+
+/////////////////////////////////////////////////////////////
+//
+// SPNEGO.C
+//
+// SPNEGO Token Handler Source File
+//
+// Contains implementation of SPNEGO Token Handling API
+// as defined in SPNEGO.H.
+//
+/////////////////////////////////////////////////////////////
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <memory.h>
+#include "spnego.h"
+#include "derparse.h"
+#include "spnegoparse.h"
+
+//
+// Defined in DERPARSE.C
+//
+
+extern MECH_OID g_stcMechOIDList [];
+
+
+/**********************************************************************/
+/** **/
+/** **/
+/** **/
+/** **/
+/** SPNEGO Token Handler API implementation **/
+/** **/
+/** **/
+/** **/
+/** **/
+/**********************************************************************/
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Function:
+// spnegoInitFromBinary
+//
+// Parameters:
+// [in] pbTokenData - Binary Token Data
+// [in] ulLength - Length of binary Token Data
+// [out] phSpnegoToken - SPNEGO_TOKEN_HANDLE pointer
+//
+// Returns:
+// int Success - SPNEGO_E_SUCCESS
+// Failure - SPNEGO API Error code
+//
+// Comments :
+// Initializes a SPNEGO_TOKEN_HANDLE from the supplied
+// binary data. Data is copied locally. Returned data structure
+// must be freed by calling spnegoFreeData().
+//
+////////////////////////////////////////////////////////////////////////////
+
+int spnegoInitFromBinary( unsigned char* pbTokenData, unsigned long ulLength, SPNEGO_TOKEN_HANDLE* phSpnegoToken )
+{
+ int nReturn = SPNEGO_E_INVALID_PARAMETER;
+ SPNEGO_TOKEN** ppSpnegoToken = (SPNEGO_TOKEN**) phSpnegoToken;
+
+ // Pass off to a handler function that allows tighter control over how the token structure
+ // is handled. In this case, we want the token data copied and we want the associated buffer
+ // freed.
+ nReturn = InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYDATA,
+ SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA, pbTokenData,
+ ulLength, ppSpnegoToken );
+
+ return nReturn;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Function:
+// spnegoCreateNegTokenInit
+//
+// Parameters:
+// [in] MechType - MechType to specify in MechTypeList element
+// [in] ucContextFlags - Context Flags element value
+// [in] pbMechToken - Pointer to binary MechToken Data
+// [in] ulMechTokenLen - Length of MechToken Data
+// [in] pbMechListMIC - Pointer to binary MechListMIC Data
+// [in] ulMechListMICLen - Length of MechListMIC Data
+// [out] phSpnegoToken - SPNEGO_TOKEN_HANDLE pointer
+//
+// Returns:
+// int Success - SPNEGO_E_SUCCESS
+// Failure - SPNEGO API Error code
+//
+// Comments :
+// Initializes a SPNEGO_TOKEN_HANDLE for a NegTokenInit type
+// from the supplied parameters. ucContextFlags may be 0 or must be
+// a valid flag combination. MechToken data can be NULL - if not, it
+// must correspond to the MechType. MechListMIC can also be NULL.
+// Returned data structure must be freed by calling spnegoFreeData().
+//
+////////////////////////////////////////////////////////////////////////////
+
+int spnegoCreateNegTokenInit( SPNEGO_MECH_OID MechType,
+ unsigned char ucContextFlags, unsigned char* pbMechToken,
+ unsigned long ulMechTokenLen, unsigned char* pbMechListMIC,
+ unsigned long ulMechListMICLen, SPNEGO_TOKEN_HANDLE* phSpnegoToken )
+{
+ int nReturn = SPNEGO_E_INVALID_PARAMETER;
+ long nTokenLength = 0L;
+ long nInternalTokenLength = 0L;
+ unsigned char* pbTokenData = NULL;
+ SPNEGO_TOKEN** ppSpnegoToken = (SPNEGO_TOKEN**) phSpnegoToken;
+
+ if ( NULL != ppSpnegoToken &&
+ IsValidMechOid( MechType ) &&
+ IsValidContextFlags( ucContextFlags ) )
+ {
+ // Get the actual token size
+
+ if ( ( nReturn = CalculateMinSpnegoInitTokenSize( ulMechTokenLen, ulMechListMICLen,
+ MechType, ( ucContextFlags != 0L ),
+ &nTokenLength, &nInternalTokenLength ) )
+ == SPNEGO_E_SUCCESS )
+ {
+ // Allocate a buffer to hold the data.
+ pbTokenData = calloc( 1, nTokenLength );
+
+ if ( NULL != pbTokenData )
+ {
+
+ // Now write the token
+ if ( ( nReturn = CreateSpnegoInitToken( MechType,
+ ucContextFlags, pbMechToken,
+ ulMechTokenLen, pbMechListMIC,
+ ulMechListMICLen, pbTokenData,
+ nTokenLength, nInternalTokenLength ) )
+ == SPNEGO_E_SUCCESS )
+ {
+
+ // This will copy our allocated pointer, and ensure that the sructure cleans
+ // up the data later
+ nReturn = InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYPTR,
+ SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA,
+ pbTokenData, nTokenLength, ppSpnegoToken );
+
+ }
+
+ // Cleanup on failure
+ if ( SPNEGO_E_SUCCESS != nReturn )
+ {
+ free( pbTokenData );
+ }
+
+ } // IF alloc succeeded
+ else
+ {
+ nReturn = SPNEGO_E_OUT_OF_MEMORY;
+ }
+
+ } // If calculated token size
+
+ } // IF Valid Parameters
+
+ return nReturn;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Function:
+// spnegoCreateNegTokenTarg
+//
+// Parameters:
+// [in] MechType - MechType to specify in supported MechType element
+// [in] spnegoNegResult - NegResult value
+// [in] pbMechToken - Pointer to response MechToken Data
+// [in] ulMechTokenLen - Length of MechToken Data
+// [in] pbMechListMIC - Pointer to binary MechListMIC Data
+// [in] ulMechListMICLen - Length of MechListMIC Data
+// [out] phSpnegoToken - SPNEGO_TOKEN_HANDLE pointer
+//
+// Returns:
+// int Success - SPNEGO_E_SUCCESS
+// Failure - SPNEGO API Error code
+//
+// Comments :
+// Initializes a SPNEGO_TOKEN_HANDLE for a NegTokenTarg type
+// from the supplied parameters. MechToken data can be NULL - if not,
+// it must correspond to the MechType. MechListMIC can also be NULL.
+// Returned data structure must be freed by calling spnegoFreeData().
+//
+////////////////////////////////////////////////////////////////////////////
+
+int spnegoCreateNegTokenTarg( SPNEGO_MECH_OID MechType,
+ SPNEGO_NEGRESULT spnegoNegResult, unsigned char* pbMechToken,
+ unsigned long ulMechTokenLen, unsigned char* pbMechListMIC,
+ unsigned long ulMechListMICLen, SPNEGO_TOKEN_HANDLE* phSpnegoToken )
+{
+ int nReturn = SPNEGO_E_INVALID_PARAMETER;
+ long nTokenLength = 0L;
+ long nInternalTokenLength = 0L;
+ unsigned char* pbTokenData = NULL;
+ SPNEGO_TOKEN** ppSpnegoToken = (SPNEGO_TOKEN**) phSpnegoToken;
+
+ //
+ // spnego_mech_oid_NotUsed and spnego_negresult_NotUsed
+ // are okay here, however a valid MechOid is required
+ // if spnego_negresult_success or spnego_negresult_incomplete
+ // is specified.
+ //
+
+ if ( NULL != ppSpnegoToken &&
+
+ ( IsValidMechOid( MechType ) ||
+ spnego_mech_oid_NotUsed == MechType ) &&
+
+ ( IsValidNegResult( spnegoNegResult ) ||
+ spnego_negresult_NotUsed == spnegoNegResult ) &&
+
+ !( !IsValidMechOid( MechType ) &&
+ ( spnego_negresult_success == spnegoNegResult ||
+ spnego_negresult_incomplete == spnegoNegResult ) ) )
+ {
+
+ // Get the actual token size
+
+ if ( ( nReturn = CalculateMinSpnegoTargTokenSize( MechType, spnegoNegResult, ulMechTokenLen,
+ ulMechListMICLen, &nTokenLength,
+ &nInternalTokenLength ) )
+ == SPNEGO_E_SUCCESS )
+ {
+ // Allocate a buffer to hold the data.
+ pbTokenData = calloc( 1, nTokenLength );
+
+ if ( NULL != pbTokenData )
+ {
+
+ // Now write the token
+ if ( ( nReturn = CreateSpnegoTargToken( MechType,
+ spnegoNegResult, pbMechToken,
+ ulMechTokenLen, pbMechListMIC,
+ ulMechListMICLen, pbTokenData,
+ nTokenLength, nInternalTokenLength ) )
+ == SPNEGO_E_SUCCESS )
+ {
+
+ // This will copy our allocated pointer, and ensure that the sructure cleans
+ // up the data later
+ nReturn = InitTokenFromBinary( SPNEGO_TOKEN_INTERNAL_COPYPTR,
+ SPNEGO_TOKEN_INTERNAL_FLAGS_FREEDATA,
+ pbTokenData, nTokenLength, ppSpnegoToken );
+
+ }
+
+ // Cleanup on failure
+ if ( SPNEGO_E_SUCCESS != nReturn )
+ {
+ free( pbTokenData );
+ }
+
+ } // IF alloc succeeded
+ else
+ {
+ nReturn = SPNEGO_E_OUT_OF_MEMORY;
+ }
+
+ } // If calculated token size
+
+ } // IF Valid Parameters
+
+ return nReturn;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Function:
+// spnegoTokenGetBinary
+//
+// Parameters:
+// [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
+// [out] pbTokenData - Buffer to copy token into
+// [in/out] pulDataLen - Length of pbTokenData buffer, filled out
+// with actual size used upon function return.
+//
+// Returns:
+// int Success - SPNEGO_E_SUCCESS
+// Failure - SPNEGO API Error code
+//
+// Comments :
+// Copies binary SPNEGO token data from hSpnegoToken into the user
+// supplied buffer. If pbTokenData is NULL, or the value in pulDataLen
+// is too small, the function will return SPNEGO_E_BUFFER_TOO_SMALL and
+// fill out pulDataLen with the minimum required buffer size.
+//
+////////////////////////////////////////////////////////////////////////////
+
+int spnegoTokenGetBinary( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pbTokenData,
+ unsigned long * pulDataLen )
+{
+ int nReturn = SPNEGO_E_INVALID_PARAMETER;
+ SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
+
+ // Check parameters - pbTokenData is optional
+ if ( IsValidSpnegoToken( pSpnegoToken ) &&
+ NULL != pulDataLen )
+ {
+
+ // Check for Buffer too small conditions
+ if ( NULL == pbTokenData ||
+ pSpnegoToken->ulBinaryDataLen > *pulDataLen )
+ {
+ *pulDataLen = pSpnegoToken->ulBinaryDataLen;
+ nReturn = SPNEGO_E_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ memcpy( pbTokenData, pSpnegoToken->pbBinaryData, pSpnegoToken->ulBinaryDataLen );
+ *pulDataLen = pSpnegoToken->ulBinaryDataLen;
+ nReturn = SPNEGO_E_SUCCESS;
+ }
+
+ } // IF parameters OK
+
+ return nReturn;;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Function:
+// spnegoFreeData
+//
+// Parameters:
+// [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
+//
+// Returns:
+// void
+//
+// Comments :
+// Frees up resources consumed by hSpnegoToken. The supplied data
+// pointer is invalidated by this function.
+//
+////////////////////////////////////////////////////////////////////////////
+
+void spnegoFreeData( SPNEGO_TOKEN_HANDLE hSpnegoToken )
+{
+ FreeSpnegoToken( (SPNEGO_TOKEN*) hSpnegoToken);
+ return;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Function:
+// spnegoGetTokenType
+//
+// Parameters:
+// [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
+// [out] piTokenType - Filled out with token type value.
+//
+// Returns:
+// int Success - SPNEGO_E_SUCCESS
+// Failure - SPNEGO API Error code
+//
+// Comments :
+// The function will analyze hSpnegoToken and return the appropriate
+// type in piTokenType.
+//
+////////////////////////////////////////////////////////////////////////////
+
+int spnegoGetTokenType( SPNEGO_TOKEN_HANDLE hSpnegoToken, int * piTokenType )
+{
+ int nReturn = SPNEGO_E_INVALID_PARAMETER;
+ SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
+
+ // Check parameters
+ if ( IsValidSpnegoToken( pSpnegoToken ) &&
+ NULL != piTokenType &&
+ pSpnegoToken)
+ {
+
+ // Check that the type in the structure makes sense
+ if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType ||
+ SPNEGO_TOKEN_TARG == pSpnegoToken->ucTokenType )
+ {
+ *piTokenType = pSpnegoToken->ucTokenType;
+ nReturn = SPNEGO_E_SUCCESS;
+ }
+
+ } // IF parameters OK
+
+ return nReturn;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Function:
+// spnegoIsMechTypeAvailable
+//
+// Parameters:
+// [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
+// [in] MechOID - MechOID to search MechTypeList for
+// [out] piMechTypeIndex - Filled out with index in MechTypeList
+// element if MechOID is found.
+//
+// Returns:
+// int Success - SPNEGO_E_SUCCESS
+// Failure - SPNEGO API Error code
+//
+// Comments :
+// hSpnegoToken must reference a token of type NegTokenInit. The
+// function will search the MechTypeList element for an OID corresponding
+// to the specified MechOID. If one is found, the index (0 based) will
+// be passed into the piMechTypeIndex parameter.
+//
+////////////////////////////////////////////////////////////////////////////
+
+// Returns the Initial Mech Type in the MechList element in the NegInitToken.
+int spnegoIsMechTypeAvailable( SPNEGO_TOKEN_HANDLE hSpnegoToken, SPNEGO_MECH_OID MechOID, int * piMechTypeIndex )
+{
+ int nReturn = SPNEGO_E_INVALID_PARAMETER;
+ SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
+
+ // Check parameters
+ if ( IsValidSpnegoToken( pSpnegoToken ) &&
+ NULL != piMechTypeIndex &&
+ IsValidMechOid( MechOID ) &&
+ SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
+ {
+
+ // Check if MechList is available
+ if ( pSpnegoToken->aElementArray[SPNEGO_INIT_MECHTYPES_ELEMENT].iElementPresent
+ == SPNEGO_TOKEN_ELEMENT_AVAILABLE )
+ {
+ // Locate the MechOID in the list element
+ nReturn = FindMechOIDInMechList(
+ &pSpnegoToken->aElementArray[SPNEGO_INIT_MECHTYPES_ELEMENT],
+ MechOID, piMechTypeIndex );
+ }
+ else
+ {
+ nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
+ }
+
+ } // IF parameters OK
+
+ return nReturn;;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Function:
+// spnegoGetContextFlags
+//
+// Parameters:
+// [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
+// [out] pucContextFlags - Filled out with ContextFlags value.
+//
+// Returns:
+// int Success - SPNEGO_E_SUCCESS
+// Failure - SPNEGO API Error code
+//
+// Comments :
+// hSpnegoToken must reference a token of type NegTokenInit. The
+// function will copy data from the ContextFlags element into the
+// location pucContextFlags points to. Note that the function will
+// fail if the actual ContextFlags data appears invalid.
+//
+////////////////////////////////////////////////////////////////////////////
+
+int spnegoGetContextFlags( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pucContextFlags )
+{
+ int nReturn = SPNEGO_E_INVALID_PARAMETER;
+ SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
+
+ // Check parameters
+ if ( IsValidSpnegoToken( pSpnegoToken ) &&
+ NULL != pucContextFlags &&
+ SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
+ {
+
+ // Check if ContextFlags is available
+ if ( pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].iElementPresent
+ == SPNEGO_TOKEN_ELEMENT_AVAILABLE )
+ {
+ // The length should be two, the value should show a 1 bit difference in the difference byte, and
+ // the value must be valid
+ if ( pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].nDatalength == SPNEGO_NEGINIT_MAXLEN_REQFLAGS &&
+ pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].pbData[0] == SPNEGO_NEGINIT_REQFLAGS_BITDIFF &&
+ IsValidContextFlags( pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].pbData[1] ) )
+ {
+ *pucContextFlags = pSpnegoToken->aElementArray[SPNEGO_INIT_REQFLAGS_ELEMENT].pbData[1];
+ nReturn = SPNEGO_E_SUCCESS;
+ }
+ else
+ {
+ nReturn = SPNEGO_E_INVALID_ELEMENT;
+ }
+
+ }
+ else
+ {
+ nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
+ }
+
+ } // IF parameters OK
+
+ return nReturn;;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Function:
+// spnegoGetNegotiationResult
+//
+// Parameters:
+// [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
+// [out] pnegResult - Filled out with NegResult value.
+//
+// Returns:
+// int Success - SPNEGO_E_SUCCESS
+// Failure - SPNEGO API Error code
+//
+// Comments :
+// hSpnegoToken must reference a token of type NegTokenTarg. The
+// function will copy data from the NegResult element into the
+// location pointed to by pnegResult. Note that the function will
+// fail if the actual NegResult data appears invalid.
+//
+////////////////////////////////////////////////////////////////////////////
+
+int spnegoGetNegotiationResult( SPNEGO_TOKEN_HANDLE hSpnegoToken, SPNEGO_NEGRESULT* pnegResult )
+{
+ int nReturn = SPNEGO_E_INVALID_PARAMETER;
+ SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
+
+ // Check parameters
+ if ( IsValidSpnegoToken( pSpnegoToken ) &&
+ NULL != pnegResult &&
+ SPNEGO_TOKEN_TARG == pSpnegoToken->ucTokenType )
+ {
+
+ // Check if NegResult is available
+ if ( pSpnegoToken->aElementArray[SPNEGO_TARG_NEGRESULT_ELEMENT].iElementPresent
+ == SPNEGO_TOKEN_ELEMENT_AVAILABLE )
+ {
+ // Must be 1 byte long and a valid value
+ if ( pSpnegoToken->aElementArray[SPNEGO_TARG_NEGRESULT_ELEMENT].nDatalength == SPNEGO_NEGTARG_MAXLEN_NEGRESULT &&
+ IsValidNegResult( *pSpnegoToken->aElementArray[SPNEGO_TARG_NEGRESULT_ELEMENT].pbData ) )
+ {
+ *pnegResult = *pSpnegoToken->aElementArray[SPNEGO_TARG_NEGRESULT_ELEMENT].pbData;
+ nReturn = SPNEGO_E_SUCCESS;
+ }
+ else
+ {
+ nReturn = SPNEGO_E_INVALID_ELEMENT;
+ }
+ }
+ else
+ {
+ nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
+ }
+
+ } // IF parameters OK
+
+ return nReturn;;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Function:
+// spnegoGetSupportedMechType
+//
+// Parameters:
+// [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
+// [out] pMechOID - Filled out with Supported MechType value.
+//
+// Returns:
+// int Success - SPNEGO_E_SUCCESS
+// Failure - SPNEGO API Error code
+//
+// Comments :
+// hSpnegoToken must reference a token of type NegTokenTarg. The
+// function will check the Supported MechType element, and if it
+// corresponds to a supported MechType ( spnego_mech_oid_Kerberos_V5_Legacy
+// or spnego_mech_oid_Kerberos_V5 ), will set the location pointed
+// to by pMechOID equal to the appropriate value.
+//
+////////////////////////////////////////////////////////////////////////////
+
+int spnegoGetSupportedMechType( SPNEGO_TOKEN_HANDLE hSpnegoToken, SPNEGO_MECH_OID* pMechOID )
+{
+ int nReturn = SPNEGO_E_INVALID_PARAMETER;
+ int nCtr = 0L;
+ long nLength = 0L;
+ SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
+
+ // Check parameters
+ if ( IsValidSpnegoToken( pSpnegoToken ) &&
+ NULL != pMechOID &&
+ SPNEGO_TOKEN_TARG == pSpnegoToken->ucTokenType )
+ {
+
+ // Check if MechList is available
+ if ( pSpnegoToken->aElementArray[SPNEGO_TARG_SUPPMECH_ELEMENT].iElementPresent
+ == SPNEGO_TOKEN_ELEMENT_AVAILABLE )
+ {
+
+ for ( nCtr = 0;
+ nReturn != SPNEGO_E_SUCCESS &&
+ g_stcMechOIDList[nCtr].eMechanismOID != spnego_mech_oid_NotUsed;
+ nCtr++ )
+ {
+
+ if ( ( nReturn = ASNDerCheckOID(
+ pSpnegoToken->aElementArray[SPNEGO_TARG_SUPPMECH_ELEMENT].pbData,
+ nCtr,
+ pSpnegoToken->aElementArray[SPNEGO_TARG_SUPPMECH_ELEMENT].nDatalength,
+ &nLength ) ) == SPNEGO_E_SUCCESS )
+ {
+ *pMechOID = nCtr;
+ }
+
+ } // For enum MechOIDs
+
+
+ }
+ else
+ {
+ nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
+ }
+
+ } // IF parameters OK
+
+ return nReturn;;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Function:
+// spnegoTokenGetMechToken
+//
+// Parameters:
+// [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
+// [out] pbTokenData - Buffer to copy MechToken into
+// [in/out] pulDataLen - Length of pbTokenData buffer, filled out
+// with actual size used upon function return.
+//
+// Returns:
+// int Success - SPNEGO_E_SUCCESS
+// Failure - SPNEGO API Error code
+//
+// Comments :
+// hSpnegoToken can point to either NegTokenInit or a NegTokenTarg token.
+// The function will copy the MechToken (the initial MechToken if
+// NegTokenInit, the response MechToken if NegTokenTarg) from the
+// underlying token into the buffer pointed to by pbTokenData. If
+// pbTokenData is NULL, or the value in pulDataLen is too small, the
+// function will return SPNEGO_E_BUFFER_TOO_SMALL and fill out pulDataLen
+// with the minimum required buffer size. The token can then be passed
+// to a GSS-API function for processing.
+//
+////////////////////////////////////////////////////////////////////////////
+
+int spnegoGetMechToken( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pbTokenData, unsigned long* pulDataLen )
+{
+ int nReturn = SPNEGO_E_INVALID_PARAMETER;
+ SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
+ SPNEGO_ELEMENT* pSpnegoElement = NULL;
+
+ // Check parameters
+ if ( IsValidSpnegoToken( pSpnegoToken ) &&
+ NULL != pulDataLen )
+ {
+
+ // Point at the proper Element
+ if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
+ {
+ pSpnegoElement = &pSpnegoToken->aElementArray[SPNEGO_INIT_MECHTOKEN_ELEMENT];
+ }
+ else
+ {
+ pSpnegoElement = &pSpnegoToken->aElementArray[SPNEGO_TARG_RESPTOKEN_ELEMENT];
+ }
+
+ // Check if MechType is available
+ if ( SPNEGO_TOKEN_ELEMENT_AVAILABLE == pSpnegoElement->iElementPresent )
+ {
+ // Check for Buffer too small conditions
+ if ( NULL == pbTokenData ||
+ pSpnegoElement->nDatalength > *pulDataLen )
+ {
+ *pulDataLen = pSpnegoElement->nDatalength;
+ nReturn = SPNEGO_E_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ // Copy Memory
+ memcpy( pbTokenData, pSpnegoElement->pbData, pSpnegoElement->nDatalength );
+ *pulDataLen = pSpnegoElement->nDatalength;
+ nReturn = SPNEGO_E_SUCCESS;
+ }
+ }
+ else
+ {
+ nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
+ }
+
+ } // IF parameters OK
+
+ return nReturn;;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Function:
+// spnegoTokenGetMechListMIC
+//
+// Parameters:
+// [in] hSpnegoToken - Initialized SPNEGO_TOKEN_HANDLE
+// [out] pbTokenData - Buffer to copy MechListMIC data into
+// [in/out] pulDataLen - Length of pbTokenData buffer, filled out
+// with actual size used upon function return.
+//
+// Returns:
+// int Success - SPNEGO_E_SUCCESS
+// Failure - SPNEGO API Error code
+//
+// Comments :
+// hSpnegoToken can point to either NegTokenInit or a NegTokenTarg token.
+// The function will copy the MechListMIC data from the underlying token
+// into the buffer pointed to by pbTokenData. If pbTokenData is NULL,
+// or the value in pulDataLen is too small, the function will return
+// SPNEGO_E_BUFFER_TOO_SMALL and fill out pulDataLen with the minimum
+// required buffer size.
+//
+////////////////////////////////////////////////////////////////////////////
+
+int spnegoGetMechListMIC( SPNEGO_TOKEN_HANDLE hSpnegoToken, unsigned char* pbMICData, unsigned long* pulDataLen )
+{
+ int nReturn = SPNEGO_E_INVALID_PARAMETER;
+ SPNEGO_TOKEN* pSpnegoToken = (SPNEGO_TOKEN*) hSpnegoToken;
+ SPNEGO_ELEMENT* pSpnegoElement = NULL;
+
+ // Check parameters
+ if ( IsValidSpnegoToken( pSpnegoToken ) &&
+ NULL != pulDataLen )
+ {
+
+ // Point at the proper Element
+ if ( SPNEGO_TOKEN_INIT == pSpnegoToken->ucTokenType )
+ {
+ pSpnegoElement = &pSpnegoToken->aElementArray[SPNEGO_INIT_MECHLISTMIC_ELEMENT];
+ }
+ else
+ {
+ pSpnegoElement = &pSpnegoToken->aElementArray[SPNEGO_TARG_MECHLISTMIC_ELEMENT];
+ }
+
+ // Check if MechType is available
+ if ( SPNEGO_TOKEN_ELEMENT_AVAILABLE == pSpnegoElement->iElementPresent )
+ {
+ // Check for Buffer too small conditions
+ if ( NULL == pbMICData ||
+ pSpnegoElement->nDatalength > *pulDataLen )
+ {
+ *pulDataLen = pSpnegoElement->nDatalength;
+ nReturn = SPNEGO_E_BUFFER_TOO_SMALL;
+ }
+ else
+ {
+ // Copy Memory
+ memcpy( pbMICData, pSpnegoElement->pbData, pSpnegoElement->nDatalength );
+ *pulDataLen = pSpnegoElement->nDatalength;
+ nReturn = SPNEGO_E_SUCCESS;
+ }
+ }
+ else
+ {
+ nReturn = SPNEGO_E_ELEMENT_UNAVAILABLE;
+ }
+
+ } // IF parameters OK
+
+ return nReturn;;
+}
+