diff options
Diffstat (limited to 'usr/src/lib/libsmbfs/smb/spnego.c')
-rw-r--r-- | usr/src/lib/libsmbfs/smb/spnego.c | 797 |
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;; +} + |