spnego.c revision 4bff34e37def8a90f9194d81bc345c52ba20086a
// 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;;
}