// Copyright 2012 Nexenta Systems, Inc. All rights reserved. // 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. // ///////////////////////////////////////////////////////////// #include #include #include #include #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: // spnegoCreateNegTokenHint // // Parameters: // [in] pMechTypeList - List of MechTypes (OIDs) to include // [in] MechTypeCnt - Length of MechTypes array // [in] pbPrincipal - Principal name for MechListMIC // [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 token // from the supplied parameters. The token created is the "hint" // used (for example) in the response to an SMB negotiate protocol. // Returned data structure must be freed by calling spnegoFreeData(). // // The "hint" tells the client what authentication methods this // server supports (the ones in the MechTypeList). The Principal // name historically was the server's own SPN, but recent versions // of windows only supply: "not_defined_in_RFC4178@please_ignore" // So if you want to be nice to your clients, provide the host SPN, // otherwise provide the bogus SPN string like recent windows. // //////////////////////////////////////////////////////////////////////////// int spnegoCreateNegTokenHint( SPNEGO_MECH_OID *pMechTypeList, int MechTypeCnt, unsigned char *pbPrincipal, SPNEGO_TOKEN_HANDLE* phSpnegoToken ) { int nReturn; long nTokenLength = 0L; long nInternalTokenLength = 0L; unsigned long ulPrincipalLen; unsigned char* pbMechListMIC; unsigned long ulMechListMICLen; unsigned char* pbTokenData = NULL; SPNEGO_TOKEN** ppSpnegoToken = (SPNEGO_TOKEN**) phSpnegoToken; if ( NULL == ppSpnegoToken || NULL == pbPrincipal ) return (SPNEGO_E_INVALID_PARAMETER); /* * Get the actual token size */ ulPrincipalLen = strlen((char *)pbPrincipal); ulMechListMICLen = ASNDerCalcElementLength( ulPrincipalLen, NULL ); nReturn = CalculateMinSpnegoInitTokenSize( 0, /* ulMechTokenLen */ ulMechListMICLen, pMechTypeList, MechTypeCnt, 0, /* nReqFlagsAvailable */ &nTokenLength, &nInternalTokenLength ); if ( nReturn != SPNEGO_E_SUCCESS ) return (nReturn); // Allocate a buffer to hold the data. pbTokenData = calloc( 1, nTokenLength ); if ( NULL == pbTokenData ) return ( SPNEGO_E_OUT_OF_MEMORY ); /* * Construct the MechListMIC */ pbMechListMIC = pbTokenData + (nTokenLength - ulMechListMICLen); (void) ASNDerWriteElement( pbMechListMIC, SPNEGO_NEGINIT_ELEMENT_MECHTYPES, GENERALSTR, pbPrincipal, ulPrincipalLen ); // Now write the token nReturn = CreateSpnegoInitToken( pMechTypeList, MechTypeCnt, 0, /* ContextFlags */ NULL, 0, /* MechToken, len */ pbMechListMIC, ulMechListMICLen, pbTokenData, nTokenLength, nInternalTokenLength ); if ( nReturn != SPNEGO_E_SUCCESS ) { free( pbTokenData ); return (nReturn); } // 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 ( nReturn != SPNEGO_E_SUCCESS ) { free( pbTokenData ); return (nReturn); } return (SPNEGO_E_SUCCESS); } ///////////////////////////////////////////////////////////////////////////// // // 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, 1, ( 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, 1, 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 ) ) { // 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;; }