2N/A/*
2N/A * // Copyright (C) 2002 Microsoft Corporation
2N/A * // All rights reserved.
2N/A * //
2N/A * // THIS CODE AND INFORMATION IS PROVIDED "AS IS"
2N/A * // WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
2N/A * // OR IMPLIED, INCLUDING BUT NOT LIMITED
2N/A * // TO THE IMPLIED WARRANTIES OF MERCHANTIBILITY
2N/A * // AND/OR FITNESS FOR A PARTICULAR PURPOSE.
2N/A * //
2N/A * // Date - 10/08/2002
2N/A * // Author - Sanj Surati
2N/A */
2N/A
2N/A/*
2N/A * DERPARSE.C
2N/A *
2N/A * SPNEGO Token Handler Source File
2N/A *
2N/A * Contains implementation of ASN.1 DER read/write functions
2N/A * as defined in DERPARSE.H.
2N/A */
2N/A
2N/A#include <stdlib.h>
2N/A#include <stdio.h>
2N/A#include <memory.h>
2N/A#include <sys/byteorder.h>
2N/A#include <smb/spnego.h>
2N/A#include "smbfs_derparse.h"
2N/A
2N/A/*
2N/A * The GSS Mechanism OID enumeration values (SPNEGO_MECH_OID) control which
2N/A * offset in the array below, that a mechanism can be found.
2N/A */
2N/A#pragma error_messages(off, E_INITIALIZATION_TYPE_MISMATCH)
2N/AMECH_OID g_stcMechOIDList [] =
2N/A{
2N/A {"\x06\x09\x2a\x86\x48\x82\xf7\x12\x01\x02\x02", 11, 9,
2N/A spnego_mech_oid_Kerberos_V5_Legacy }, /* 1.2.840.48018.1.2.2 */
2N/A {"\x06\x09\x2a\x86\x48\x86\xf7\x12\x01\x02\x02", 11, 9,
2N/A spnego_mech_oid_Kerberos_V5 }, /* 1.2.840.113554.1.2.2 */
2N/A {"\x06\x06\x2b\x06\x01\x05\x05\x02", 8, 6,
2N/A spnego_mech_oid_Spnego }, /* 1.3.6.1.5.5.2 */
2N/A {"\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a", 12, 10,
2N/A spnego_mech_oid_NTLMSSP }, /* 1.3.6.1.4.1.311.2.2.10 */
2N/A {"", 0, 0, spnego_mech_oid_NotUsed } /* Placeholder */
2N/A};
2N/A#pragma error_messages(default, E_INITIALIZATION_TYPE_MISMATCH)
2N/A
2N/A/*
2N/A *
2N/A * Function:
2N/A * ASNDerGetLength
2N/A *
2N/A * Parameters:
2N/A * [in] pbLengthData - DER Length Data
2N/A * [in] nBoundaryLength - Length that value must not exceed.
2N/A * [out] pnLength - Filled out with length value
2N/A * [out] pnNumLengthBytes - Filled out with number of bytes
2N/A * consumed by DER length.
2N/A *
2N/A * Returns:
2N/A * int Success - SPNEGO_E_SUCCESS
2N/A * Failure - SPNEGO API Error code
2N/A *
2N/A * Comments :
2N/A * Interprets the data at pbLengthData as a DER length. The length must
2N/A * fit within the bounds of nBoundary length. We do not currently
2N/A * process lengths that take more than 4 bytes.
2N/A *
2N/A */
2N/Astatic int
2N/Asmbfs_ASNDerGetLength(unsigned char *pbLengthData, long nBoundaryLength,
2N/A long *pnLength, long *pnNumLengthBytes)
2N/A{
2N/A int nReturn = SPNEGO_E_INVALID_LENGTH;
2N/A int nNumLengthBytes = 0;
2N/A
2N/A /* First check if the extended length bit is set */
2N/A if (*pbLengthData & LEN_XTND) {
2N/A /*
2N/A * Lower 7 bits contain number of trailing bytes that describe
2N/A * the length.
2N/A */
2N/A nNumLengthBytes = *pbLengthData & LEN_MASK;
2N/A
2N/A /*
2N/A * Check that the number of bytes we are about to read is within
2N/A * our boundary constraints
2N/A */
2N/A if (nNumLengthBytes <= nBoundaryLength - 1) {
2N/A
2N/A /* We won't deal with lengths greater than 4 bytes */
2N/A if (nNumLengthBytes >= 1 && nNumLengthBytes <= 4) {
2N/A /* 0 out the initial length */
2N/A *pnLength = 0L;
2N/A
2N/A /* Bump by 1 byte */
2N/A pbLengthData++;
2N/A
2N/A#ifdef _LITTLE_ENDIAN
2N/A switch (nNumLengthBytes) {
2N/A
2N/A case 1:
2N/A {
2N/A *(((unsigned char *)pnLength)) \
2N/A = *pbLengthData;
2N/A break;
2N/A }
2N/A
2N/A case 2:
2N/A {
2N/A *(((unsigned char *)pnLength)) \
2N/A = *(pbLengthData + 1);
2N/A *(((unsigned char *)pnLength) \
2N/A + 1) = *(pbLengthData);
2N/A break;
2N/A }
2N/A
2N/A case 3:
2N/A {
2N/A *(((unsigned char *)pnLength)) \
2N/A = *(pbLengthData + 2);
2N/A *(((unsigned char *)pnLength) \
2N/A + 2) = *(pbLengthData + 1);
2N/A *(((unsigned char *)pnLength) \
2N/A + 3) = *(pbLengthData);
2N/A break;
2N/A }
2N/A
2N/A case 4:
2N/A {
2N/A *(((unsigned char *)pnLength)) \
2N/A = *(pbLengthData + 3);
2N/A *(((unsigned char *)pnLength) \
2N/A + 1) = *(pbLengthData + 2);
2N/A *(((unsigned char *)pnLength) \
2N/A + 2) = *(pbLengthData + 1);
2N/A *(((unsigned char *)pnLength) \
2N/A + 3) = *(pbLengthData);
2N/A break;
2N/A }
2N/A
2N/A } /* SWITCH ( nNumLengthBytes ) */
2N/A#else
2N/A /*
2N/A * We are Big-Endian, so the length can be
2N/A * copied in from the source as is. Ensure that
2N/A * we adjust for the number of bytes we actually
2N/A * copy.
2N/A */
2N/A (void) memcpy(((unsigned char *) pnLength) + \
2N/A (4 - nNumLengthBytes), pbLengthData,
2N/A nNumLengthBytes);
2N/A#endif
2N/A
2N/A /* Account for the initial length byte */
2N/A *pnNumLengthBytes = nNumLengthBytes + 1;
2N/A nReturn = SPNEGO_E_SUCCESS;
2N/A
2N/A } /* IF Valid Length */
2N/A } /* IF num bytes to read is within the boundary length */
2N/A } else {
2N/A
2N/A /*
2N/A * Extended bit is not set, so the length is in the value and
2N/A * the one byte describes the length.
2N/A */
2N/A *pnLength = *pbLengthData & LEN_MASK;
2N/A *pnNumLengthBytes = 1;
2N/A nReturn = SPNEGO_E_SUCCESS;
2N/A }
2N/A
2N/A return (nReturn);
2N/A}
2N/A
2N/A
2N/A/*
2N/A *
2N/A * Function:
2N/A * smbfs_ASNDerCheckToken
2N/A *
2N/A * Parameters:
2N/A * [in] pbTokenData - Token Data
2N/A * [in] nToken - Token identifier to check for
2N/A * [in] nLengthWithToken - Expected token length (with data)
2N/A * [in] nBoundaryLength - Length that value must not exceed.
2N/A * [out] pnLength - Filled out with data length
2N/A * [out] pnTokenLength - Filled out with number of bytes
2N/A * consumed by token identifier and length.
2N/A *
2N/A * Returns:
2N/A * int Success - SPNEGO_E_SUCCESS
2N/A * Failure - SPNEGO API Error code
2N/A *
2N/A * Comments :
2N/A * Checks the data pointed to by pbTokenData for the specified token
2N/A * identifier and the length that immediately follows. If
2N/A * nLengthWithToken is > 0, the calculated length must match. The
2N/A * length must also not exceed the specified boundary length .
2N/A *
2N/A */
2N/Aint
2N/Asmbfs_ASNDerCheckToken(unsigned char *pbTokenData, unsigned char nToken,
2N/A long nLengthWithToken, long nBoundaryLength, long *pnLength,
2N/A long *pnTokenLength)
2N/A{
2N/A
2N/A int nReturn = SPNEGO_E_INVALID_LENGTH;
2N/A long nNumLengthBytes = 0L;
2N/A
2N/A /* Make sure that we've at least got 2 bytes of room to work with */
2N/A if (nBoundaryLength >= 2) {
2N/A
2N/A /* The 1st byte of token data MUST match the specified token */
2N/A if (*pbTokenData == nToken) {
2N/A
2N/A /* Next byte indicates the length */
2N/A pbTokenData++;
2N/A
2N/A nReturn = smbfs_ASNDerGetLength(pbTokenData,
2N/A nBoundaryLength, pnLength, &nNumLengthBytes);
2N/A
2N/A /* Get the length described by the token */
2N/A if (nReturn == SPNEGO_E_SUCCESS) {
2N/A /*
2N/A * Verify that the length is LESS THAN the
2N/A * boundary length (this should prevent us
2N/A * walking out of our buffer)
2N/A */
2N/A if ((nBoundaryLength - \
2N/A (nNumLengthBytes + 1) < *pnLength))
2N/A nReturn = SPNEGO_E_INVALID_LENGTH;
2N/A
2N/A /* check length */
2N/A if (nLengthWithToken > 0L) {
2N/A
2N/A /* Check that expected length matches */
2N/A if ((nLengthWithToken - \
2N/A (nNumLengthBytes + 1)) != *pnLength)
2N/A nReturn = \
2N/A SPNEGO_E_INVALID_LENGTH;
2N/A
2N/A } /* IF need to validate length */
2N/A
2N/A if (SPNEGO_E_SUCCESS == nReturn)
2N/A *pnTokenLength = nNumLengthBytes + 1;
2N/A } /* IF ASNDerGetLength */
2N/A } else {
2N/A nReturn = SPNEGO_E_TOKEN_NOT_FOUND;
2N/A }
2N/A } /* IF Boundary Length is at least 2 bytes */
2N/A
2N/A return (nReturn);
2N/A}
2N/A
2N/A/*
2N/A *
2N/A * Function:
2N/A * smbfs_ASNDerCheckOID
2N/A *
2N/A * Parameters:
2N/A * [in] pbTokenData - Token Data
2N/A * [in] nMechOID - OID we are looking for
2N/A * [in] nBoundaryLength - Length that value must not exceed.
2N/A * [out] pnTokenLength - Filled out with number of bytes
2N/A * consumed by token and data.
2N/A *
2N/A * Returns:
2N/A * int Success - SPNEGO_E_SUCCESS
2N/A * Failure - SPNEGO API Error code
2N/A *
2N/A * Comments :
2N/A * Checks the data pointed to by pbTokenData for the specified OID.
2N/A *
2N/A */
2N/Aint smbfs_ASNDerCheckOID(unsigned char *pbTokenData, SPNEGO_MECH_OID nMechOID,
2N/A long nBoundaryLength, long *pnTokenLength)
2N/A{
2N/A int nReturn = 0L;
2N/A long nLength = 0L;
2N/A
2N/A /* Verify that we have an OID token */
2N/A nReturn = smbfs_ASNDerCheckToken(pbTokenData, OID, 0L, nBoundaryLength,
2N/A &nLength, pnTokenLength);
2N/A if (nReturn == SPNEGO_E_SUCCESS) {
2N/A /* Add the data length to the Token Length */
2N/A *pnTokenLength += nLength;
2N/A
2N/A /*
2N/A * Token Lengths plus the actual length must match the length in
2N/A * our OID list element. If it doesn't, we're done.
2N/A */
2N/A if (*pnTokenLength == g_stcMechOIDList[nMechOID].iLen) {
2N/A
2N/A /* Memcompare the token and the expected field */
2N/A if (memcmp(pbTokenData,
2N/A g_stcMechOIDList[nMechOID].ucOid,
2N/A *pnTokenLength) != 0)
2N/A nReturn = SPNEGO_E_UNEXPECTED_OID;
2N/A } else {
2N/A nReturn = SPNEGO_E_UNEXPECTED_OID;
2N/A }
2N/A } /* IF OID Token CHecks */
2N/A
2N/A return (nReturn);
2N/A}
2N/A
2N/A/*
2N/A *
2N/A * Function:
2N/A * smbfs_ASNDerCalcNumLengthBytes
2N/A *
2N/A * Parameters:
2N/A * [in] nLength - Length to calculate length bytes for.
2N/A *
2N/A * Returns:
2N/A * int Number of bytes necessary to represent length
2N/A *
2N/A * Comments :
2N/A * Helper function to calculate the number of length bytes necessary to
2N/A * represent a length value. For our purposes, a 32-bit value should be
2N/A * enough to describea length.
2N/A *
2N/A */
2N/Astatic int
2N/Asmbfs_ASNDerCalcNumLengthBytes(long nLength)
2N/A{
2N/A if (nLength <= 0x7F) {
2N/A /*
2N/A * A single byte will be sufficient for describing this length.
2N/A * The byte will simply contain the length
2N/A */
2N/A return (1);
2N/A } else if (nLength <= 0xFF) {
2N/A /*
2N/A * Two bytes are necessary, one to say how many following bytes
2N/A * describe the length, and one to give the length
2N/A */
2N/A return (2);
2N/A } else if (nLength <= 0xFFFF) {
2N/A /*
2N/A * Three bytes are necessary, one to say how many following
2N/A * bytes describe the length, and two to give the length.
2N/A */
2N/A return (3);
2N/A } else if (nLength <= 0xFFFFFF) {
2N/A /*
2N/A * Four bytes are necessary, one to say how many following bytes
2N/A * describe the length, and three to give the length
2N/A */
2N/A return (4);
2N/A } else {
2N/A /*
2N/A * Five bytes are necessary, one to say how many following bytes
2N/A * describe the length, and four to give the length
2N/A */
2N/A return (5);
2N/A }
2N/A}
2N/A
2N/A
2N/A/*
2N/A *
2N/A * Function:
2N/A * smbfs_ASNDerCalcTokenLength
2N/A *
2N/A * Parameters:
2N/A * [in] nLength - Length to calculate length bytes for.
2N/A * [in] nDataLength - Actual Data length value.
2N/A *
2N/A * Returns:
2N/A * long Number of bytes necessary to represent a token, length and data
2N/A *
2N/A * Comments :
2N/A * Helper function to calculate a token and value size, based on a
2N/A * supplied length value, and any binary data that will need to be
2N/A * written out.
2N/A *
2N/A */
2N/Along
2N/Asmbfs_ASNDerCalcTokenLength(long nLength, long nDataLength)
2N/A{
2N/A /*
2N/A * Add a byte to the length size to account for a single byte to
2N/A * hold the token type.
2N/A */
2N/A long nTotalLength = smbfs_ASNDerCalcNumLengthBytes(nLength) + 1;
2N/A
2N/A return (nTotalLength + nDataLength);
2N/A}
2N/A
2N/A
2N/A/*
2N/A *
2N/A * Function:
2N/A * smbfs_ASNDerCalcElementLength
2N/A *
2N/A * Parameters:
2N/A * [in] nDataLength - Length of data.
2N/A * [out] pnInternalLength - Filled out with length of element
2N/A * without sequence info.
2N/A *
2N/A * Returns:
2N/A * long Number of bytes necessary to represent an element
2N/A *
2N/A * Comments :
2N/A * Helper function to calculate an element length. An element consists
2N/A * of a sequence token, a type token and then the data.
2N/A *
2N/A */
2N/Along
2N/Asmbfs_ASNDerCalcElementLength(long nDataLength, long *pnInternalLength)
2N/A{
2N/A /* First the type token and the actual data */
2N/A long nTotalLength;
2N/A
2N/A nTotalLength = smbfs_ASNDerCalcTokenLength(nDataLength, nDataLength);
2N/A
2N/A /* Internal length is the length without the element sequence token */
2N/A if (NULL != pnInternalLength)
2N/A *pnInternalLength = nTotalLength;
2N/A
2N/A /*
2N/A * Next add in the element's sequence token (remember that its
2N/A * length is the total length of the type token and data)
2N/A */
2N/A nTotalLength += smbfs_ASNDerCalcTokenLength(nTotalLength, 0L);
2N/A
2N/A return (nTotalLength);
2N/A}
2N/A
2N/A/*
2N/A *
2N/A * Function:
2N/A * smbfs_ASNDerCalcMechListLength
2N/A *
2N/A * Parameters:
2N/A * [in] mechoid - Mech OID to put in list.
2N/A * [out] pnInternalLength - Filled out with length of element
2N/A * without the primary sequence token.
2N/A *
2N/A * Returns:
2N/A * long Number of bytes necessary to represent a mechList
2N/A *
2N/A * Comments :
2N/A * Helper function to calculate a MechList length. A mechlist consists
2N/A * of a NegTokenInit sequence token, a sequence token for the MechList
2N/A * and finally a list of OIDs. In our case, we only really have one
2N/A * OID.
2N/A *
2N/A */
2N/Along
2N/Asmbfs_ASNDerCalcMechListLength(SPNEGO_MECH_OID mechoid, long *pnInternalLength)
2N/A{
2N/A /* First the OID */
2N/A long nTotalLength = g_stcMechOIDList[mechoid].iLen;
2N/A
2N/A /* Next add in a sequence token */
2N/A nTotalLength += smbfs_ASNDerCalcTokenLength(nTotalLength, 0L);
2N/A
2N/A /* Internal length is the length without the element sequence token */
2N/A if (NULL != pnInternalLength)
2N/A *pnInternalLength = nTotalLength;
2N/A
2N/A /* Finally add in the element's sequence token */
2N/A nTotalLength += smbfs_ASNDerCalcTokenLength(nTotalLength, 0L);
2N/A
2N/A return (nTotalLength);
2N/A}
2N/A
2N/A
2N/A/*
2N/A *
2N/A * Function:
2N/A * smbfs_ASNDerWriteLength
2N/A *
2N/A * Parameters:
2N/A * [out] pbData - Buffer to write into.
2N/A * [in] nLength - Length to write out.
2N/A *
2N/A * Returns:
2N/A * int Number of bytes written out
2N/A *
2N/A * Comments :
2N/A * Helper function to write out a length value following DER rules .
2N/A *
2N/A */
2N/Aint
2N/Asmbfs_ASNDerWriteLength(unsigned char *pbData, long nLength)
2N/A{
2N/A int nNumBytesRequired = smbfs_ASNDerCalcNumLengthBytes(nLength);
2N/A int nNumLengthBytes = nNumBytesRequired - 1;
2N/A
2N/A if (nNumBytesRequired > 1) {
2N/A
2N/A /* Write out the number of bytes following which will be used */
2N/A *pbData = (unsigned char)(LEN_XTND | nNumLengthBytes);
2N/A
2N/A /* Point to where we'll actually write the length */
2N/A pbData++;
2N/A
2N/A#ifdef _LITTLE_ENDIAN
2N/A switch (nNumLengthBytes) {
2N/A case 1:
2N/A {
2N/A /*
2N/A * Cast the length to a single byte, since we
2N/A * know that it is 0x7F or less (or we wouldn't
2N/A * only need a single byte).
2N/A */
2N/A *pbData = (unsigned char)nLength;
2N/A break;
2N/A }
2N/A
2N/A case 2:
2N/A {
2N/A *pbData = *(((unsigned char *)&nLength) + 1);
2N/A *(pbData + 1) = *(((unsigned char *)&nLength));
2N/A break;
2N/A }
2N/A
2N/A case 3:
2N/A {
2N/A *pbData = *(((unsigned char *)&nLength) + 3);
2N/A *(pbData + 1) = *(((unsigned char *)&nLength) \
2N/A + 2);
2N/A *(pbData + 2) = *(((unsigned char *)&nLength));
2N/A break;
2N/A }
2N/A
2N/A case 4:
2N/A {
2N/A *pbData = *(((unsigned char *)&nLength) + 3);
2N/A *(pbData + 1) = *(((unsigned char *)&nLength) \
2N/A + 2);
2N/A *(pbData + 2) = *(((unsigned char *)&nLength) \
2N/A + 1);
2N/A *(pbData + 3) = *(((unsigned char *)&nLength));
2N/A break;
2N/A }
2N/A } /* SWITCH ( nNumLengthBytes ) */
2N/A
2N/A#else
2N/A /*
2N/A * We are Big-Endian, so the length can be copied in from the
2N/A * source as is. Ensure that we adjust for the number of bytes
2N/A * we actually copy.
2N/A */
2N/A (void) memcpy(pbData,
2N/A ((unsigned char *)&nLength) + (4 - nNumLengthBytes),
2N/A nNumLengthBytes);
2N/A#endif
2N/A
2N/A } else {
2N/A /*
2N/A * Cast the length to a single byte, since we know that it
2N/A * is 0x7F or less (or we wouldn't only need a single byte).
2N/A */
2N/A *pbData = (unsigned char)nLength;
2N/A }
2N/A
2N/A return (nNumBytesRequired);
2N/A}
2N/A
2N/A/*
2N/A *
2N/A * Function:
2N/A * smbfs_ASNDerWriteToken
2N/A *
2N/A * Parameters:
2N/A * [out] pbData - Buffer to write into.
2N/A * [in] ucType - Token Type
2N/A * [in] pbTokenValue - Actual Value
2N/A * [in] nLength - Length of Data.
2N/A *
2N/A * Returns:
2N/A * int Number of bytes written out
2N/A *
2N/A * Comments :
2N/A * Helper function to write out a token and any associated data. If
2N/A * pbTokenValue is non-NULL, then it is written out in addition to the
2N/A * token identifier and the length bytes.
2N/A *
2N/A */
2N/Aint
2N/Asmbfs_ASNDerWriteToken(unsigned char *pbData, unsigned char ucType,
2N/A unsigned char *pbTokenValue, long nLength)
2N/A{
2N/A int nTotalBytesWrittenOut = 0L;
2N/A int nNumLengthBytesWritten = 0L;
2N/A
2N/A /* Write out the type */
2N/A *pbData = ucType;
2N/A
2N/A /* Wrote 1 byte, and move data pointer */
2N/A nTotalBytesWrittenOut++;
2N/A pbData++;
2N/A
2N/A /* Write out the length and adjust the number of bytes written out */
2N/A nNumLengthBytesWritten = smbfs_ASNDerWriteLength(pbData, nLength);
2N/A
2N/A nTotalBytesWrittenOut += nNumLengthBytesWritten;
2N/A pbData += nNumLengthBytesWritten;
2N/A
2N/A /*
2N/A * Write out the token value if we got one. The assumption is that the
2N/A * nLength value indicates how many bytes are in pbTokenValue.
2N/A */
2N/A if (NULL != pbTokenValue) {
2N/A (void) memcpy(pbData, pbTokenValue, nLength);
2N/A nTotalBytesWrittenOut += nLength;
2N/A }
2N/A
2N/A return (nTotalBytesWrittenOut);
2N/A}
2N/A
2N/A/*
2N/A *
2N/A * Function:
2N/A * smbfs_ASNDerWriteOID
2N/A *
2N/A * Parameters:
2N/A * [out] pbData - Buffer to write into.
2N/A * [in] eMechOID - OID to write out.
2N/A *
2N/A * Returns:
2N/A * int Number of bytes written out
2N/A *
2N/A * Comments :
2N/A * Helper function to write out an OID. For these we have the raw bytes
2N/A * listed in a global structure. The caller simply indicates which OID
2N/A * should be written and we will splat out the data.
2N/A *
2N/A */
2N/Aint
2N/Asmbfs_ASNDerWriteOID(unsigned char *pbData, SPNEGO_MECH_OID eMechOID)
2N/A{
2N/A (void) memcpy(pbData, g_stcMechOIDList[eMechOID].ucOid,
2N/A g_stcMechOIDList[eMechOID].iLen);
2N/A
2N/A return (g_stcMechOIDList[eMechOID].iLen);
2N/A}
2N/A
2N/A
2N/A/*
2N/A *
2N/A * Function:
2N/A * smbfs_ASNDerWriteMechList
2N/A *
2N/A * Parameters:
2N/A * [out] pbData - Buffer to write into.
2N/A * [in] eMechOID - OID to put in MechList.
2N/A *
2N/A * Returns:
2N/A * int Number of bytes written out
2N/A *
2N/A * Comments :
2N/A * Helper function to write out a MechList. A MechList consists of the
2N/A * Init Token Sequence, a sequence token and then the list of OIDs. In
2N/A * our case the OID is from a global array of known OIDs.
2N/A *
2N/A */
2N/Along
2N/Asmbfs_ASNDerWriteMechList(unsigned char *pbData, SPNEGO_MECH_OID mechoid)
2N/A{
2N/A /* First get the length */
2N/A long nInternalLength = 0L;
2N/A long nMechListLength = 0L;
2N/A long nTempLength = 0L;
2N/A
2N/A nMechListLength = smbfs_ASNDerCalcMechListLength(mechoid,
2N/A &nInternalLength);
2N/A nTempLength = smbfs_ASNDerWriteToken(pbData,
2N/A SPNEGO_NEGINIT_ELEMENT_MECHTYPES, NULL, nInternalLength);
2N/A
2N/A /* Adjust the data pointer */
2N/A pbData += nTempLength;
2N/A
2N/A /*
2N/A * Now write the Sequence token and the OID (the OID is a BLOB in the
2N/A * global structure.
2N/A */
2N/A nTempLength = smbfs_ASNDerWriteToken(pbData,
2N/A SPNEGO_CONSTRUCTED_SEQUENCE, g_stcMechOIDList[mechoid].ucOid,
2N/A g_stcMechOIDList[mechoid].iLen);
2N/A
2N/A return (nMechListLength);
2N/A}
2N/A
2N/A
2N/A/*
2N/A *
2N/A * Function:
2N/A * smbfs_ASNDerWriteElement
2N/A *
2N/A * Parameters:
2N/A * [out] pbData - Buffer to write into.
2N/A * [in] ucElementSequence - Sequence Token
2N/A * [in] ucType - Token Type
2N/A * [in] pbTokenValue - Actual Value
2N/A * [in] nLength - Length of Data.
2N/A *
2N/A * Returns:
2N/A * int Number of bytes written out
2N/A *
2N/A * Comments :
2N/A * Helper function to write out a SPNEGO Token element. An element
2N/A * consists of a sequence token, a type token and the associated data.
2N/A *
2N/A */
2N/Aint
2N/Asmbfs_ASNDerWriteElement(unsigned char *pbData, unsigned char ucElementSequence,
2N/A unsigned char ucType, unsigned char *pbTokenValue, long nLength)
2N/A{
2N/A
2N/A /* First get the length */
2N/A long nInternalLength = 0L;
2N/A long nElementLength = 0L;
2N/A long nTempLength = 0L;
2N/A
2N/A nElementLength = smbfs_ASNDerCalcElementLength(nLength,
2N/A &nInternalLength);
2N/A
2N/A /* Write out the sequence byte and the length of the type and data */
2N/A nTempLength = smbfs_ASNDerWriteToken(pbData, ucElementSequence, NULL,
2N/A nInternalLength);
2N/A
2N/A /* Adjust the data pointer */
2N/A pbData += nTempLength;
2N/A
2N/A /* Now write the type and the data. */
2N/A nTempLength = smbfs_ASNDerWriteToken(pbData, ucType, pbTokenValue,
2N/A nLength);
2N/A
2N/A return (nElementLength);
2N/A}