Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1603 lines
38 KiB

//////////////////////////////////////////////////////////////////////////////
// Module : parser_util.cpp
//
// Purpose : All utility functions used by the parser
//
// Developers Name : N.Surendra Sai / Vunnam Kondal Rao
//
// History :
//
// Date Author Comments
//
// 27 Aug 2001
//
//////////////////////////////////////////////////////////////////////////////
#include "nshipsec.h"
extern HINSTANCE g_hModule;
extern void *g_AllocPtr[MAX_ARGS];
extern STORAGELOCATION g_StorageLocation;
extern DWORD ValidateBool(IN LPTSTR ppcTok);
//////////////////////////////////////////////////////////////////////////////
//
// Function : ListToSecMethod()
//
// Date of Creation : 12 Sept 2001
//
// Parameters : IN LPTSTR szText // string to convert
// IN OUT IPSEC_MM_OFFER SecMethod // target struct to be filled.
//
// Return : DWORD
// T2P_OK
// T2P_NULL_STRING
// T2P_GENERAL_PARSE_ERROR
// T2P_DUP_ALGS
// T2P_INVALID_P1GROUP
// T2P_P1GROUP_MISSING
//
// Description : converts string to Phase 1 offer
//
// History :
//
// Date Author Comments
//
//////////////////////////////////////////////////////////////////////////////
DWORD
ListToSecMethod(
IN LPTSTR szText,
IN OUT IPSEC_MM_OFFER &SecMethod
)
{
DWORD dwReturn = T2P_OK;
_TCHAR szTmp[MAX_STR_LEN] = {0};
LPTSTR pString1 = NULL;
LPTSTR pString2 = NULL;
BOOL bEncryption = FALSE;
BOOL bAuthentication = FALSE;
if (szText == NULL)
{
dwReturn = T2P_NULL_STRING;
BAIL_OUT;
}
if (_tcslen(szText) < MAX_STR_LEN)
{
_tcsncpy(szTmp, szText,MAX_STR_LEN-1);
}
else
{
dwReturn = T2P_GENERAL_PARSE_ERROR;
BAIL_OUT;
}
pString1 = _tcschr(szTmp, POTF_P1_TOKEN);
pString2 = _tcsrchr(szTmp, POTF_P1_TOKEN);
if ((pString1 != NULL) && (pString2 != NULL) && (pString1 != pString2))
{
*pString1 = '\0';
*pString2 = '\0';
++pString1;
++pString2;
// we allow the hash and encryption to be specified in either
// the first or second field
if (_tcsicmp(szTmp, POTF_P1_DES) == 0)
{
bEncryption = true;
SecMethod.EncryptionAlgorithm.uAlgoIdentifier = CONF_ALGO_DES;
SecMethod.EncryptionAlgorithm.uAlgoKeyLen = SecMethod.EncryptionAlgorithm.uAlgoRounds = 0;
}
else if (_tcsicmp(szTmp, POTF_P1_3DES) == 0)
{
bEncryption = true;
SecMethod.EncryptionAlgorithm.uAlgoIdentifier = CONF_ALGO_3_DES;
SecMethod.EncryptionAlgorithm.uAlgoKeyLen = SecMethod.EncryptionAlgorithm.uAlgoRounds = 0;
}
else if (_tcsicmp(szTmp, POTF_P1_MD5) == 0)
{
bAuthentication = true;
SecMethod.HashingAlgorithm.uAlgoIdentifier = HMAC_AUTH_ALGO_MD5;
SecMethod.HashingAlgorithm.uAlgoKeyLen = SecMethod.HashingAlgorithm.uAlgoRounds = 0;
}
else if ( (_tcsicmp(szTmp, POTF_P1_SHA1) == 0) )
{
bAuthentication = true;
SecMethod.HashingAlgorithm.uAlgoIdentifier = HMAC_AUTH_ALGO_SHA1;
SecMethod.HashingAlgorithm.uAlgoKeyLen = SecMethod.HashingAlgorithm.uAlgoRounds = 0;
}
else
{
// parse error
dwReturn = T2P_GENERAL_PARSE_ERROR;
}
if (_tcsicmp(pString1, POTF_P1_DES) == 0 && !bEncryption)
{
bEncryption = true;
SecMethod.EncryptionAlgorithm.uAlgoIdentifier = CONF_ALGO_DES;
SecMethod.EncryptionAlgorithm.uAlgoKeyLen = SecMethod.EncryptionAlgorithm.uAlgoRounds = 0;
}
else if (_tcsicmp(pString1, POTF_P1_3DES) == 0 && !bEncryption)
{
bEncryption = true;
SecMethod.EncryptionAlgorithm.uAlgoIdentifier = CONF_ALGO_3_DES;
SecMethod.EncryptionAlgorithm.uAlgoKeyLen = SecMethod.EncryptionAlgorithm.uAlgoRounds = 0;
}
else if (_tcsicmp(pString1, POTF_P1_MD5) == 0 && !bAuthentication)
{
bAuthentication = true;
SecMethod.HashingAlgorithm.uAlgoIdentifier = HMAC_AUTH_ALGO_MD5;
SecMethod.HashingAlgorithm.uAlgoKeyLen = SecMethod.HashingAlgorithm.uAlgoRounds = 0;
}
else if ((_tcsicmp(pString1, POTF_P1_SHA1) == 0) && !bAuthentication)
{
bAuthentication = true;
SecMethod.HashingAlgorithm.uAlgoIdentifier = HMAC_AUTH_ALGO_SHA1;
SecMethod.HashingAlgorithm.uAlgoKeyLen = SecMethod.HashingAlgorithm.uAlgoRounds = 0;
}
else
{
// parse error
dwReturn = T2P_GENERAL_PARSE_ERROR;
}
// now for the group
if (isdigit(pString2[0]))
{
switch (pString2[0])
{
case '1' :
SecMethod.dwDHGroup = POTF_OAKLEY_GROUP1;
break;
case '2' :
SecMethod.dwDHGroup = POTF_OAKLEY_GROUP2;
break;
case '3' :
SecMethod.dwDHGroup = POTF_OAKLEY_GROUP2048;
break;
default :
dwReturn = T2P_INVALID_P1GROUP;
break;
}
}
else
{
dwReturn = T2P_P1GROUP_MISSING;
}
}
else
{
dwReturn = T2P_GENERAL_PARSE_ERROR;
}
error:
return dwReturn;
}
//////////////////////////////////////////////////////////////////////////////
//
// Function : StringToRootcaAuth()
//
// Date of Creation : 13th Aug 2001
//
// Parameters : IN szText // String to be converted
// IN OUT AuthInfo // Target struct to be filled
//
// Return : DWORD
// T2P_OK
// T2P_NO_PRESHARED_KEY
// T2P_INVALID_AUTH_METHOD
// T2P_ENCODE_FAILED
// T2P_NULL_STRING
//
// Description : This Function takes user input authentication string, validates
// and puts into Main mode auth info structure
//
// History :
//
// Date Author Comments
//
//////////////////////////////////////////////////////////////////////////////
DWORD
StringToRootcaAuth(
IN LPTSTR szText,
IN OUT INT_IPSEC_MM_AUTH_INFO &AuthInfo
)
{
DWORD dwStatus = ERROR_SUCCESS,dwReturn = T2P_OK;
LPTSTR szTemp = NULL;
DWORD dwTextLen = 0;
DWORD dwInfoLen = 0;
LPBYTE pbInfo = NULL;
if (szText == NULL)
{
dwReturn = T2P_NULL_STRING;
BAIL_OUT;
}
AuthInfo.pAuthInfo = NULL;
AuthInfo.dwAuthInfoSize = 0;
dwTextLen = _tcslen(szText);
dwInfoLen = _tcslen(szText);
szTemp = (LPTSTR) calloc(dwInfoLen+1,sizeof(_TCHAR));
if(szTemp == NULL)
{
dwReturn = ERROR_OUTOFMEMORY;
BAIL_OUT;
}
AuthInfo.AuthMethod = IKE_RSA_SIGNATURE;
_tcsncpy(szTemp, szText, dwInfoLen);
AuthInfo.dwAuthInfoSize = _tcslen(szTemp)+1;
pbInfo = (LPBYTE) new _TCHAR[AuthInfo.dwAuthInfoSize];
if(pbInfo == NULL)
{
dwReturn = ERROR_OUTOFMEMORY;
BAIL_OUT;
}
memcpy(pbInfo, szTemp, sizeof(TCHAR)*AuthInfo.dwAuthInfoSize);
AuthInfo.dwAuthInfoSize *= sizeof(WCHAR);
AuthInfo.pAuthInfo = pbInfo;
LPBYTE asnCert = NULL;
dwStatus = EncodeCertificateName((LPTSTR) AuthInfo.pAuthInfo,&asnCert,&AuthInfo.dwAuthInfoSize);
delete [] AuthInfo.pAuthInfo;
AuthInfo.pAuthInfo = NULL;
if(dwStatus == ERROR_SUCCESS )
{
AuthInfo.pAuthInfo = asnCert;
dwReturn = T2P_OK;
}
else
{
if(dwStatus == ERROR_OUTOFMEMORY) // Either there was a error out of memory
{
dwReturn = ERROR_OUTOFMEMORY;
BAIL_OUT;
}
AuthInfo.pAuthInfo = NULL;
AuthInfo.dwAuthInfoSize = 0;
dwReturn = T2P_ENCODE_FAILED; // ... else the encode failed.
}
error:
if (szTemp)
{
free(szTemp);
}
return dwReturn;
}
//////////////////////////////////////////////////////////////////////////////
//
// Function : ListToOffer()
//
// Date of Creation : 13th Aug 2001
//
// Parameters : IN LPTSTR szText // string to convert
// IN OUT IPSEC_QM_OFFER &Offer // target struct to be filled.
//
// Return : DWORD
// T2P_OK
// T2P_NULL_STRING
// T2P_P2_SECLIFE_INVALID
// T2P_P2_KBLIFE_INVALID
// T2P_INVALID_P2REKEY_UNIT
// T2P_INVALID_HASH_ALG
// T2P_GENERAL_PARSE_ERROR
// T2P_DUP_ALGS
// T2P_NONE_NONE
// T2P_INCOMPLETE_ESPALGS
// T2P_INVALID_IPSECPROT
// T2P_P2_KBLIFE_INVALID
// T2P_AHESP_INVALID
//
// Description : Converts string to Phase 2 offer (quick mode)
//
// History :
//
// Date Author Comments
//
//////////////////////////////////////////////////////////////////////////////
DWORD
ListToOffer(
IN LPTSTR szText,
IN OUT IPSEC_QM_OFFER &Offer
)
{
DWORD dwReturn = T2P_OK,dwStatus = 0;
_TCHAR szTmp[MAX_STR_LEN] = {0};
LPTSTR pAnd = NULL,pOptions = NULL,pString = NULL;
BOOL bLifeSpecified = FALSE;
BOOL bDataSpecified = FALSE;
if (szText == NULL)
{
dwReturn = T2P_NULL_STRING;
BAIL_OUT;
}
Offer.dwNumAlgos = 0;
Offer.dwPFSGroup = 0;
if (_tcslen(szText) < MAX_STR_LEN)
{
_tcsncpy(szTmp, szText,MAX_STR_LEN-1);
}
else
{
dwReturn = T2P_GENERAL_PARSE_ERROR;
BAIL_OUT;
}
pOptions = _tcsrchr(szTmp, POTF_NEGPOL_CLOSE);
if ((pOptions != NULL) && *(pOptions + 1) != '\0' && *(pOptions + 1) == POTF_PT_TOKEN && *(pOptions + 2) != '\0')
{
++pOptions; // we have crossed ']'
*pOptions = '\0'; // We have zero'd *pOption
++pOptions; // we have crossed ':'
pString = _tcschr(pOptions, POTF_REKEY_TOKEN);
if (pString != NULL)
{
*pString = '\0';
++pString;
switch (pString[_tcslen(pString) - 1]) // First parse Last one ie out of 200K/300S ->300S
{
case 'k' :
case 'K' :
bDataSpecified = TRUE;
pString[_tcslen(pString) - 1] = '\0';
dwStatus = _stscanf(pString,_TEXT("%u"),&Offer.Lifetime.uKeyExpirationKBytes);
if (dwStatus != 1)
{
dwReturn = T2P_P2_KBLIFE_INVALID;
}
else
{
if (!IsWithinLimit(Offer.Lifetime.uKeyExpirationKBytes,P2_Kb_LIFE_MIN,P2_Kb_LIFE_MAX) )
{
dwReturn = T2P_P2_KBLIFE_INVALID;
}
}
break;
case 's' :
case 'S' :
bLifeSpecified = TRUE;
pString[_tcslen(pString) - 1] = '\0';
dwStatus = _stscanf(pString,_TEXT("%u"),&Offer.Lifetime.uKeyExpirationTime);
if (dwStatus != 1)
{
dwReturn = T2P_P2_SECLIFE_INVALID;
}
else if (!IsWithinLimit(Offer.Lifetime.uKeyExpirationTime,P2_Sec_LIFE_MIN,P2_Sec_LIFE_MAX) )
{
dwReturn = T2P_P2_SECLIFE_INVALID;
}
break;
default :
dwReturn = T2P_P2_KS_INVALID;
break;
}
}
if(dwReturn == T2P_OK)
{
switch (pOptions[_tcslen(pOptions) - 1])
{
case 'k' :
case 'K' :
if(!bDataSpecified )
{
pOptions[_tcslen(pOptions) - 1] = '\0';
dwStatus = _stscanf(pOptions,_TEXT("%u"),&Offer.Lifetime.uKeyExpirationKBytes);
if (dwStatus != 1)
{
dwReturn = T2P_P2_KBLIFE_INVALID;
}
else if (!IsWithinLimit(Offer.Lifetime.uKeyExpirationKBytes,P2_Kb_LIFE_MIN,P2_Kb_LIFE_MAX) )
{
dwReturn = T2P_P2_KBLIFE_INVALID;
}
}
else
{
dwReturn = T2P_P2_KS_INVALID;
}
break;
case 's' :
case 'S' :
if(!bLifeSpecified )
{
pOptions[_tcslen(pOptions) - 1] = '\0';
dwStatus = _stscanf(pOptions,_TEXT("%u"),&Offer.Lifetime.uKeyExpirationTime);
if (dwStatus != 1)
{
dwReturn = T2P_P2REKEY_TOO_LOW;
}
else if (!IsWithinLimit(Offer.Lifetime.uKeyExpirationTime,P2_Sec_LIFE_MIN,P2_Sec_LIFE_MAX) )
{
dwReturn = T2P_P2_SECLIFE_INVALID;
}
}
else
{
dwReturn = T2P_P2_KS_INVALID;
}
break;
default :
dwReturn = T2P_INVALID_P2REKEY_UNIT;
break;
}
}
}
if(dwReturn==T2P_OK)
{
pAnd = _tcschr(szTmp, POTF_NEGPOL_AND);
if ( pAnd != NULL )
{
//
// we have an AND proposal
//
*pAnd = '\0';
++pAnd;
dwReturn = TextToAlgoInfo(szTmp, Offer.Algos[Offer.dwNumAlgos]);
++Offer.dwNumAlgos;
if ( T2P_SUCCESS(dwReturn) )
{
dwReturn = TextToAlgoInfo(pAnd, Offer.Algos[Offer.dwNumAlgos]);
if( (Offer.Algos[Offer.dwNumAlgos].Operation) == (Offer.Algos[Offer.dwNumAlgos-1].Operation) )
{
dwReturn = T2P_AHESP_INVALID;
}
++Offer.dwNumAlgos;
}
}
else
{
dwReturn = TextToAlgoInfo(szTmp, Offer.Algos[Offer.dwNumAlgos]);
++Offer.dwNumAlgos;
}
}
error:
return dwReturn;
}
//////////////////////////////////////////////////////////////////////////////
//
// Function : TextToAlgoInfo()
//
// Date of Creation : 26th Aug 2001
//
// Parameters : IN LPTSTR szText // string to convert
// IN OUT IPSEC_QM_ALGO &algoInfo // target struct to be filled.
//
// Return : DWORD
// T2P_OK
// T2P_INVALID_HASH_ALG
// T2P_GENERAL_PARSE_ERROR
// T2P_DUP_ALGS
// T2P_NONE_NONE
// T2P_INCOMPLETE_ESPALGS
// T2P_INVALID_IPSECPROT
// T2P_NULL_STRING
//
// Description : Converts string to IPSEC_QM_ALGO,parses AH[alg] or ESP[hashalg,confalg]
//
// History :
//
// Date Author Comments
//
//////////////////////////////////////////////////////////////////////////////
DWORD
TextToAlgoInfo(
IN LPTSTR szText,
OUT IPSEC_QM_ALGO & algoInfo
)
{
DWORD dwReturn = T2P_OK;
_TCHAR szTmp[MAX_STR_LEN] = {0};
LPTSTR pOpen = NULL,pClose = NULL,pString = NULL;
BOOL bEncryption = FALSE; // these are used for processing Auth+Encryption
BOOL bAuthentication= FALSE; // defaults to NONE+NONE
if (szText == NULL)
{
dwReturn = T2P_NULL_STRING;
BAIL_OUT;
}
if (_tcslen(szText) < MAX_STR_LEN)
{
_tcsncpy(szTmp, szText,MAX_STR_LEN-1);
}
else
{
dwReturn = T2P_GENERAL_PARSE_ERROR;
BAIL_OUT;
}
algoInfo.uAlgoKeyLen = algoInfo.uAlgoRounds = 0;
pOpen = _tcschr(szTmp, POTF_NEGPOL_OPEN);
pClose = _tcsrchr(szTmp, POTF_NEGPOL_CLOSE);
if ((pOpen != NULL) && (pClose != NULL) && (*(pClose + 1) == '\0')) // defense
{
*pOpen = '\0';
*pClose = '\0';
++pOpen;
if (_tcsicmp(szTmp, POTF_NEGPOL_AH) == 0)
{
algoInfo.Operation = AUTHENTICATION;
if (_tcsicmp(pOpen, POTF_NEGPOL_MD5) == 0)
{
algoInfo.uAlgoIdentifier = AUTH_ALGO_MD5;
}
else if (_tcsicmp(pOpen, POTF_NEGPOL_SHA1) == 0)
{
algoInfo.uAlgoIdentifier = AUTH_ALGO_SHA1;
}
else
{
dwReturn = T2P_INVALID_HASH_ALG;
}
}
else if (_tcsicmp(szTmp, POTF_NEGPOL_ESP) == 0)
{
algoInfo.Operation = ENCRYPTION;
pString = _tcschr(pOpen, POTF_ESPTRANS_TOKEN);
if (pString != NULL)
{
*pString = '\0';
++pString;
// we allow the hash and encryption to be specified in either
// the first or second field
if (_tcsicmp(pOpen, POTF_NEGPOL_DES) == 0)
{
bEncryption = true;
algoInfo.uAlgoIdentifier = CONF_ALGO_DES;
}
else if (_tcsicmp(pOpen, POTF_NEGPOL_3DES) == 0)
{
bEncryption = true;
algoInfo.uAlgoIdentifier = CONF_ALGO_3_DES;
}
else if (_tcsicmp(pOpen, POTF_NEGPOL_MD5) == 0)
{
bAuthentication = true;
algoInfo.uSecAlgoIdentifier = HMAC_AUTH_ALGO_MD5;
}
else if (_tcsicmp(pOpen, POTF_NEGPOL_SHA1) == 0)
{
bAuthentication = true;
algoInfo.uSecAlgoIdentifier = HMAC_AUTH_ALGO_SHA1;
}
else if (_tcsicmp(pOpen, POTF_NEGPOL_NONE) != 0)
{
//
// parse error
//
dwReturn = T2P_GENERAL_PARSE_ERROR;
BAIL_OUT;
}
// now the second one
if (_tcsicmp(pString, POTF_NEGPOL_DES) == 0 && !bEncryption)
{
bEncryption = true;
algoInfo.uAlgoIdentifier = CONF_ALGO_DES;
}
else if (_tcsicmp(pString, POTF_NEGPOL_3DES) == 0 && !bEncryption)
{
bEncryption = true;
algoInfo.uAlgoIdentifier = CONF_ALGO_3_DES;
}
else if (_tcsicmp(pString, POTF_NEGPOL_MD5) == 0 && !bAuthentication)
{
bAuthentication = true;
algoInfo.uSecAlgoIdentifier = HMAC_AUTH_ALGO_MD5;
}
else if ((_tcsicmp(pString, POTF_NEGPOL_SHA1) == 0) && !bAuthentication)
{
bAuthentication = true;
algoInfo.uSecAlgoIdentifier = HMAC_AUTH_ALGO_SHA1;
}
else if (_tcsicmp(pString, POTF_NEGPOL_NONE) != 0)
{
//
// parse error
//
dwReturn = T2P_GENERAL_PARSE_ERROR;
}
// now, fill in the NONE policies or detect NONE, NONE
if (!bAuthentication && !bEncryption)
{
dwReturn = T2P_NONE_NONE;
}
else if (!bAuthentication)
{
algoInfo.uSecAlgoIdentifier = HMAC_AUTH_ALGO_NONE;
}
else if (!bEncryption)
{
algoInfo.uAlgoIdentifier = CONF_ALGO_NONE;
}
}
else // error
{
dwReturn = T2P_INCOMPLETE_ESPALGS;
}
}
else
{
dwReturn = T2P_INVALID_IPSECPROT;
}
}
else // error
{
dwReturn = T2P_GENERAL_PARSE_ERROR;
}
error:
return dwReturn;
}
//////////////////////////////////////////////////////////////////////////////
//
// Function : LoadQMOfferDefaults()
//
// Date of Creation : 12th Aug 2001
//
// Parameters : IN OUT Offer // target struct to be filled.
//
// Description : Fills the Default values for Quick mode offer structure
//
// History :
//
// Date Author Comments
//
//////////////////////////////////////////////////////////////////////////////
VOID
LoadQMOfferDefaults(
IN OUT IPSEC_QM_OFFER & Offer
)
{
Offer.Lifetime.uKeyExpirationTime = POTF_DEFAULT_P2REKEY_TIME;
Offer.Lifetime.uKeyExpirationKBytes = POTF_DEFAULT_P2REKEY_BYTES;
Offer.dwFlags = 0;
Offer.bPFSRequired = FALSE;
Offer.dwPFSGroup = 0;
Offer.dwNumAlgos = 2;
Offer.dwReserved = 0;
Offer.Algos[0].Operation = ENCRYPTION;
Offer.Algos[0].uAlgoIdentifier = 0;
Offer.Algos[0].uSecAlgoIdentifier = (HMAC_AUTH_ALGO_ENUM)0;
Offer.Algos[0].uAlgoKeyLen = 0;
Offer.Algos[0].uSecAlgoKeyLen = 0;
Offer.Algos[0].uAlgoRounds = 0;
Offer.Algos[0].uSecAlgoRounds = 0;
Offer.Algos[0].MySpi = 0;
Offer.Algos[0].PeerSpi = 0;
Offer.Algos[1].Operation = (IPSEC_OPERATION)0;
Offer.Algos[1].uAlgoIdentifier = 0;
Offer.Algos[1].uSecAlgoIdentifier = (HMAC_AUTH_ALGO_ENUM)0;
Offer.Algos[1].uAlgoKeyLen = 0;
Offer.Algos[1].uSecAlgoKeyLen = 0;
Offer.Algos[1].uAlgoRounds = 0;
Offer.Algos[1].uSecAlgoRounds = 0;
Offer.Algos[1].MySpi = 0;
Offer.Algos[1].PeerSpi = 0;
}
//////////////////////////////////////////////////////////////////////////////
//
// Function : LoadSecMethodDefaults()
//
// Date of Creation: 7th Aug 2001
//
// Parameters : IN OUT SecMethod // Struct which is filled with default values
//
// Return : VOID
//
// Description : It Fills default values for IPSEC_MM_OFFER
//
// Revision History:
//
// Date Author Comments
//
//////////////////////////////////////////////////////////////////////////////
VOID
LoadSecMethodDefaults(
IN OUT IPSEC_MM_OFFER &SecMethod
)
{
SecMethod.Lifetime.uKeyExpirationTime = POTF_DEFAULT_P1REKEY_TIME;
SecMethod.Lifetime.uKeyExpirationKBytes = 0;
SecMethod.dwFlags = 0;
SecMethod.dwQuickModeLimit = POTF_DEFAULT_P1REKEY_QMS;
SecMethod.dwDHGroup = 0;
SecMethod.EncryptionAlgorithm.uAlgoIdentifier = 0;
SecMethod.EncryptionAlgorithm.uAlgoKeyLen = 0;
SecMethod.EncryptionAlgorithm.uAlgoRounds = 0;
SecMethod.HashingAlgorithm.uAlgoIdentifier = 0;
SecMethod.HashingAlgorithm.uAlgoKeyLen = 0;
SecMethod.HashingAlgorithm.uAlgoRounds = 0;
}
//////////////////////////////////////////////////////////////////////////////
//
// Function : LoadKerbAuthInfo()
//
// Date of Creation : 08th Jan 2002
//
// Parameters : IN LPTSTR pszInput,
// OUT PPARSER_PKT pParser,
// IN DWORD dwTagType,
// IN PDWORD pdwUsed,
// IN DWORD dwCount,
//
// Return : ERROR_SUCESS
// ERROR_INVALID_OPTION_VALUE
// ERROR_OUTOFMEMORY
//
// Description : Validates Yes/No
//
//
// History :
//
// Date Author Comments
//
//////////////////////////////////////////////////////////////////////////////
DWORD
LoadKerbAuthInfo(
IN LPTSTR pszInput,
OUT PPARSER_PKT pParser,
IN DWORD dwTagType,
IN PDWORD pdwUsed,
IN DWORD dwCount
)
{
DWORD dwReturn = ERROR_SUCCESS;
DWORD dwStatus = 0;
PSTA_MM_AUTH_METHODS pMMInfo = NULL;
PSTA_AUTH_METHODS pInfo = NULL;
if (*pdwUsed > MAX_ARGS_LIMIT)
{
dwReturn = ERROR_OUT_OF_STRUCTURES;
BAIL_OUT;
}
pInfo = new STA_AUTH_METHODS;
if (!pInfo)
{
dwReturn = ERROR_OUTOFMEMORY;
BAIL_OUT;
}
dwStatus = ValidateBool(pszInput);
if (dwStatus != ARG_YES)
{
if (dwStatus == ARG_NO)
{
// valid parameter, but we don't enter any auth info
dwStatus = ERROR_SUCCESS;
}
else
{
dwStatus = ERRCODE_INVALID_ARG;
}
// if we get here, we didn't have a yes param value for kerberos, so don't
// generate the auth info structure
BAIL_OUT;
}
// Generate the auth info
//
dwReturn = GenerateKerbAuthInfo(&pMMInfo);
if (dwReturn != NO_ERROR)
{
BAIL_OUT;
}
pInfo->pAuthMethodInfo = pMMInfo;
pInfo->dwNumAuthInfos = 1;
pInfo->pAuthMethodInfo->dwSequence = dwCount;
// Update the parser
//
pParser->Cmd[dwCount].dwStatus = VALID_TOKEN; // one auth info struct
pParser->Cmd[dwCount].pArg = pInfo;
pParser->Cmd[dwCount].dwCmdToken = dwTagType;
pInfo = NULL;
error:
if (pInfo)
{
delete pInfo;
}
return dwReturn;
}
//////////////////////////////////////////////////////////////////////////////
//
// Function : LoadPskAuthInfo()
//
// Date of Creation : 08th Jan 2002
//
// Parameters : IN LPTSTR pszInput,
// OUT PPARSER_PKT pParser,
// IN DWORD dwTagType,
// IN PDWORD pdwUsed,
// IN DWORD dwCount,
//
// Return : ERROR_SUCESS
// ERROR_INVALID_OPTION_VALUE
// ERROR_OUTOFMEMORY
//
// Description : Validates string
//
//
// History :
//
// Date Author Comments
//
//////////////////////////////////////////////////////////////////////////////
DWORD
LoadPskAuthInfo(
IN LPTSTR pszInput,
OUT PPARSER_PKT pParser,
IN DWORD dwTagType,
IN PDWORD pdwUsed,
IN DWORD dwCount
)
{
DWORD dwReturn = ERROR_SUCCESS;
DWORD dwStatus = 0;
PSTA_MM_AUTH_METHODS pMMInfo = NULL;
PSTA_AUTH_METHODS pInfo = NULL;
if (*pdwUsed > MAX_ARGS_LIMIT)
{
dwReturn = ERROR_OUT_OF_STRUCTURES;
BAIL_OUT;
}
pInfo = new STA_AUTH_METHODS;
if (!pInfo)
{
dwReturn = ERROR_OUTOFMEMORY;
BAIL_OUT;
}
// verify there really is a string there
//
if (pszInput[0] == _TEXT('\0'))
{
dwReturn = ERRCODE_INVALID_ARG;
BAIL_OUT;
}
// Generate the auth info
//
dwReturn = GeneratePskAuthInfo(&pMMInfo, pszInput);
if (dwReturn != NO_ERROR)
{
BAIL_OUT;
}
pInfo->pAuthMethodInfo = pMMInfo;
pInfo->dwNumAuthInfos = 1;
pInfo->pAuthMethodInfo->dwSequence = dwCount;
// Update the parser
//
pParser->Cmd[dwCount].dwStatus = VALID_TOKEN; // one auth info struct
pParser->Cmd[dwCount].pArg = pInfo;
pParser->Cmd[dwCount].dwCmdToken = dwTagType;
pInfo = NULL;
error:
if (pInfo)
{
delete pInfo;
}
return dwReturn;
}
//////////////////////////////////////////////////////////////////////////////
//
// Function : EncodeCertificateName()
//
// Date of Creation : 21st Aug 2001
//
// Parameters : LPTSTR pszSubjectName,
// BYTE **EncodedName,
// PDWORD pEncodedNameLength
//
// Return : DWORD
//
// Description : This function encodes the certificate name based on the user input.
//
// History :
//
// Date Author Comments
//
//////////////////////////////////////////////////////////////////////////////
DWORD
EncodeCertificateName (
LPTSTR pszSubjectName,
BYTE **EncodedName,
PDWORD pdwEncodedNameLength
)
{
*pdwEncodedNameLength=0; DWORD dwReturn = ERROR_SUCCESS;
if (!CertStrToName( X509_ASN_ENCODING,
pszSubjectName,
CERT_X500_NAME_STR,
NULL,
NULL,
pdwEncodedNameLength,
NULL))
{
dwReturn = ERROR_INVALID_PARAMETER;
}
if(dwReturn == ERROR_SUCCESS)
{
(*EncodedName)= new BYTE[*pdwEncodedNameLength];
if(*EncodedName)
{
if (!CertStrToName( X509_ASN_ENCODING,
pszSubjectName,
CERT_X500_NAME_STR,
NULL,
(*EncodedName),
pdwEncodedNameLength,
NULL))
{
delete (*EncodedName);
(*EncodedName) = 0;
dwReturn = ERROR_INVALID_PARAMETER;
}
}
else
{
dwReturn = ERROR_OUTOFMEMORY;
}
}
return dwReturn;
}
DWORD
GenerateKerbAuthInfo(
OUT STA_MM_AUTH_METHODS** ppInfo
)
{
DWORD dwReturn = NO_ERROR;
STA_MM_AUTH_METHODS* pInfo = new STA_MM_AUTH_METHODS;
if (pInfo == NULL)
{
dwReturn = ERROR_NOT_ENOUGH_MEMORY;
BAIL_OUT;
}
ZeroMemory(pInfo, sizeof(STA_MM_AUTH_METHODS));
pInfo->pAuthenticationInfo = new INT_IPSEC_MM_AUTH_INFO;
if (pInfo->pAuthenticationInfo == NULL)
{
dwReturn = ERROR_NOT_ENOUGH_MEMORY;
BAIL_OUT;
}
ZeroMemory(pInfo->pAuthenticationInfo, sizeof(INT_IPSEC_MM_AUTH_INFO));
// Indicate kerberos
//
pInfo->pAuthenticationInfo->AuthMethod = IKE_SSPI;
*ppInfo = pInfo;
error:
if (dwReturn != NO_ERROR)
{
if (pInfo)
{
if (pInfo->pAuthenticationInfo)
{
delete pInfo->pAuthenticationInfo;
}
delete pInfo;
}
}
return dwReturn;
}
DWORD
GeneratePskAuthInfo(
OUT STA_MM_AUTH_METHODS** ppInfo,
IN LPTSTR lpKey
)
{
DWORD dwReturn = NO_ERROR;
size_t uiKeyLen = 0;
STA_MM_AUTH_METHODS* pInfo = NULL;
LPTSTR lpLocalKey;
// Allocate the info struct
//
pInfo = new STA_MM_AUTH_METHODS;
if (pInfo == NULL)
{
dwReturn = ERROR_NOT_ENOUGH_MEMORY;
BAIL_OUT;
}
ZeroMemory(pInfo, sizeof(STA_MM_AUTH_METHODS));
pInfo->pAuthenticationInfo = new INT_IPSEC_MM_AUTH_INFO;
if (pInfo->pAuthenticationInfo == NULL)
{
dwReturn = ERROR_NOT_ENOUGH_MEMORY;
BAIL_OUT;
}
ZeroMemory(pInfo->pAuthenticationInfo, sizeof(INT_IPSEC_MM_AUTH_INFO));
dwReturn = NsuStringLen(lpKey, &uiKeyLen);
if (dwReturn != ERROR_SUCCESS)
{
BAIL_OUT;
}
lpLocalKey = new TCHAR[uiKeyLen];
_tcsncpy(lpLocalKey, lpKey, uiKeyLen);
// Indicate psk
//
pInfo->pAuthenticationInfo->AuthMethod= IKE_PRESHARED_KEY;
pInfo->pAuthenticationInfo->pAuthInfo = (LPBYTE)lpLocalKey;
pInfo->pAuthenticationInfo->dwAuthInfoSize = uiKeyLen * sizeof(WCHAR);
*ppInfo = pInfo;
error:
if (dwReturn != NO_ERROR)
{
if (pInfo)
{
if (pInfo->pAuthenticationInfo)
{
delete pInfo->pAuthenticationInfo;
}
delete pInfo;
}
}
return dwReturn;
}
DWORD
GenerateRootcaAuthInfo(
OUT STA_MM_AUTH_METHODS** ppInfo,
IN LPTSTR lpRootcaInfo
)
{
DWORD dwReturn = NO_ERROR;
DWORD dwStatus = NO_ERROR;
size_t uiCertInfoLen = 0;
BOOL bCertMapSpecified = FALSE;
BOOL bCertMapping = FALSE;
BOOL bCRPExclude = FALSE;
STA_MM_AUTH_METHODS* pInfo = NULL;
PINT_IPSEC_MM_AUTH_INFO pMMAuthInfo = NULL;
// Allocate the info struct
//
pInfo = new STA_MM_AUTH_METHODS;
if (pInfo == NULL)
{
dwReturn = ERROR_NOT_ENOUGH_MEMORY;
BAIL_OUT;
}
ZeroMemory(pInfo, sizeof(STA_MM_AUTH_METHODS));
if (_tcsicmp(lpRootcaInfo,_TEXT("\0")) != 0)
{
pMMAuthInfo = new INT_IPSEC_MM_AUTH_INFO;
if(pMMAuthInfo == NULL)
{
dwReturn = ERROR_OUTOFMEMORY;
BAIL_OUT;
}
CheckForCertParamsAndRemove(lpRootcaInfo, &bCertMapSpecified, &bCertMapping, &bCRPExclude);
dwStatus = StringToRootcaAuth(lpRootcaInfo,*(pMMAuthInfo));
pInfo->bCertMappingSpecified = bCertMapSpecified;
pInfo->bCertMapping = bCertMapping;
pInfo->bCRPExclude = bCRPExclude;
pInfo->pAuthenticationInfo = pMMAuthInfo;
pMMAuthInfo = NULL;
if((dwStatus != T2P_OK) || (dwReturn != ERROR_SUCCESS) )
{
switch(dwStatus)
{
case ERROR_OUTOFMEMORY :
PrintErrorMessage(WIN32_ERR,ERROR_OUTOFMEMORY,NULL);
dwReturn = RETURN_NO_ERROR;
break;
default :
break;
}
PrintErrorMessage(IPSEC_ERR, 0, ERRCODE_ENCODE_FAILED);
dwReturn = RETURN_NO_ERROR;
BAIL_OUT;
}
}
*ppInfo = pInfo;
pInfo = NULL;
error:
if (pInfo)
{
if (pInfo->pAuthenticationInfo)
{
delete pInfo->pAuthenticationInfo;
}
delete pInfo;
}
if (pMMAuthInfo)
{
delete pMMAuthInfo;
}
return dwReturn;
}
//////////////////////////////////////////////////////////////////////////////
//
// Function : CheckForCertParamsAndRemove()
//
// Date of Creation : 28th Jan 2002
//
// Parameters : IN szText // Input String
// OUT BOOL CertMapSpecified // Certificate contains CertMap Option
// OUT BOOL CertMap // User Specified CertMap Option
// OUT BOOL CRPExclude // User specified CRP option
//
// Return : DWORD
// T2P_INVALID_AUTH_METHOD
// T2P_NULL_STRING
//
// Description : This Function takes user input authentication cert string, validates
// cert map and puts into Main mode auth info structure
//
// History :
//
// Date Author Comments
//
//////////////////////////////////////////////////////////////////////////////
DWORD
MatchKeywordAndFillValues(
const TCHAR * lptString,
const TCHAR * lptKeyword,
size_t uiKeyLen,
PBOOL pbSpecified,
PBOOL pbValue
)
{
const TCHAR TOKEN_YES [] = _TEXT("yes");
const TCHAR TOKEN_NO [] = _TEXT("no");
if ((_tcsnicmp(lptString, lptKeyword, uiKeyLen) == 0) && (lptString[uiKeyLen] == _TEXT(':')))
{
if (*pbSpecified)
{
return ERROR_TOKEN_ALREADY_IN_USE;
}
*pbSpecified = TRUE;
if (_tcsnicmp((LPTSTR)(&lptString[uiKeyLen+1]), TOKEN_YES, sizeof(TOKEN_YES)/sizeof(TCHAR) - 1) == 0)
{
*pbValue = TRUE;
}
else if (_tcsnicmp((LPTSTR)(&lptString[uiKeyLen+1]), TOKEN_NO, sizeof(TOKEN_NO)/sizeof(TCHAR) - 1) == 0)
{
*pbValue = FALSE;
}
else
{
return ERROR_INVALID_PARAMETER;
}
}
else
{
return ERROR_INVALID_DATA;
}
return ERROR_SUCCESS;
}
DWORD
CheckForCertParamsAndRemove(
IN OUT LPTSTR szText,
OUT PBOOL pbCertMapSpecified,
OUT PBOOL pbCertMap,
OUT PBOOL pbCRPExclude
)
{
DWORD dwReturn = ERROR_SUCCESS;
*pbCertMapSpecified = FALSE;
BOOL bCRPExcludeSpecified = FALSE;
BOOL bIsMatch = TRUE;
const TCHAR TOKEN_CERTMAP [] = _TEXT("certmap");
const TCHAR TOKEN_CRP_EXCLUDE [] = _TEXT("excludecaname");
// find end of string
size_t uiStrLen = 0;
dwReturn = NsuStringLen(szText, &uiStrLen);
if (dwReturn != ERROR_SUCCESS)
{
BAIL_OUT;
}
LPTSTR szTextTemp = szText + uiStrLen - 1;
while (bIsMatch && (!bCRPExcludeSpecified || !(*pbCertMapSpecified)))
{
// work back to last whitespace before last non-whitespace
while ((*szTextTemp == _TEXT(' ')) || (*szTextTemp == _TEXT('\t')))
{
*szTextTemp = _TEXT('\0');
--szTextTemp;
}
// we can't go past the start of the string, and in fact it is invalid if the cert string starts with a parameter,
// so parse accordingly
while ((szTextTemp > szText) && (*szTextTemp != _TEXT(' ')) && (*szTextTemp != _TEXT('\t')))
{
--szTextTemp;
}
if (szTextTemp == szText)
{
// we are at the start of the whole string, so there is no appropriate parameter portion or
// the certmap is invalid... just return we didn't find anything and let cert parsing figure it out
dwReturn = ERROR_SUCCESS;
BAIL_OUT;
}
++szTextTemp;
dwReturn = MatchKeywordAndFillValues(
szTextTemp,
TOKEN_CERTMAP,
sizeof(TOKEN_CERTMAP)/sizeof(TCHAR) - 1,
pbCertMapSpecified,
pbCertMap
);
switch(dwReturn)
{
case ERROR_SUCCESS:
break;
case ERROR_INVALID_DATA:
dwReturn = MatchKeywordAndFillValues(
szTextTemp,
TOKEN_CRP_EXCLUDE,
sizeof(TOKEN_CRP_EXCLUDE)/sizeof(TCHAR) - 1,
&bCRPExcludeSpecified,
pbCRPExclude
);
switch (dwReturn)
{
case ERROR_INVALID_DATA:
// we didn't match either parameter, so we're done
bIsMatch = FALSE;
dwReturn = ERROR_SUCCESS;
break;
case ERROR_SUCCESS:
break;
case ERROR_TOKEN_ALREADY_IN_USE:
case ERROR_INVALID_PARAMETER:
default:
BAIL_OUT;
break;
}
break;
case ERROR_TOKEN_ALREADY_IN_USE:
case ERROR_INVALID_PARAMETER:
default:
BAIL_OUT;
break;
}
// chop the certmap portion if it existed... we already know we are not altering anything _before_
// the start of the passed string because of the while loops above
if (bIsMatch)
{
--szTextTemp;
while ((szTextTemp > szText) && ((*szTextTemp == _TEXT(' ')) || (*szTextTemp == _TEXT('\t'))))
{
--szTextTemp;
}
++szTextTemp;
*szTextTemp = _TEXT('\0');
}
}
error:
return dwReturn;
}
///////////////////////////////////////////////////////////////////////////////
//
// ProcessEscapedCharacters
//
// every occurrence of \' in the string is shortened to "
//
// Notes:
// * this transformation occurs in place and the new string is properly
// null-terminated
// * it is not up to this routine to determine if number of quotes match,
// only to properly place interpreted escaped characters where they
// originally existed in the input string
//
// Return values:
// ERR_INVALID_ARG
// ERROR_SUCCESS
//
///////////////////////////////////////////////////////////////////////////////
DWORD ProcessEscapedCharacters(LPTSTR lptString)
{
DWORD dwReturn = ERROR_SUCCESS;
_TCHAR* src = lptString;
_TCHAR* dst = lptString;
while (*src != _TEXT('\0'))
{
switch(*src)
{
case _TEXT('\\'):
// take proper action based on escaped character found
++src;
switch(*src)
{
case _TEXT('\''):
*dst = _TEXT('\"');
break;
default:
dwReturn = ERR_INVALID_ARG;
BAIL_OUT;
break;
}
break;
default:
// copy directly, keep processing
*dst = *src;
break;
}
++dst;
++src;
}
error:
// null-terminate the string as-is, even if processing failed
*dst = _TEXT('\0');
return dwReturn;
}
VOID
AddAuthMethod(
PRULEDATA pRuleData,
PSTA_MM_AUTH_METHODS pMMAuth,
size_t *pIndex
)
{
if (pMMAuth)
{
//Certificate to account mapping issue is taken care here
if(pMMAuth->bCertMappingSpecified)
{
if((g_StorageLocation.dwLocation==IPSEC_REGISTRY_PROVIDER && IsDomainMember(g_StorageLocation.pszMachineName))||(g_StorageLocation.dwLocation==IPSEC_DIRECTORY_PROVIDER))
{
if(pMMAuth->bCertMapping)
{
pMMAuth->pAuthenticationInfo->dwAuthFlags|= IPSEC_MM_CERT_AUTH_ENABLE_ACCOUNT_MAP;
}
else
{
pMMAuth->pAuthenticationInfo->dwAuthFlags &= ~IPSEC_MM_CERT_AUTH_ENABLE_ACCOUNT_MAP;
}
}
else
{
if(pMMAuth->bCertMapping)
{
PrintMessageFromModule(g_hModule,SET_STATIC_POLICY_INVALID_CERTMAP_MSG);
}
}
}
else
{
pMMAuth->pAuthenticationInfo->dwAuthFlags &= ~IPSEC_MM_CERT_AUTH_ENABLE_ACCOUNT_MAP;
}
if(pMMAuth->bCRPExclude)
{
pMMAuth->pAuthenticationInfo->dwAuthFlags |= IPSEC_MM_CERT_AUTH_DISABLE_CERT_REQUEST;
}
else
{
pMMAuth->pAuthenticationInfo->dwAuthFlags &= ~IPSEC_MM_CERT_AUTH_DISABLE_CERT_REQUEST;
}
pRuleData->AuthInfos.pAuthMethodInfo[*pIndex].pAuthenticationInfo = pMMAuth->pAuthenticationInfo;
pMMAuth->pAuthenticationInfo = NULL;
++(*pIndex);
}
}
VOID
AddAuthMethod(
PRULEDATA pRuleData,
PSTA_AUTH_METHODS pAuthMethods,
size_t *pIndex
)
{
if (pAuthMethods)
{
AddAuthMethod(pRuleData, pAuthMethods->pAuthMethodInfo, pIndex);
}
}
DWORD
AddAllAuthMethods(
PRULEDATA pRuleData,
PSTA_AUTH_METHODS pKerbAuth,
PSTA_AUTH_METHODS pPskAuth,
PSTA_MM_AUTH_METHODS *ppRootcaMMAuth,
BOOL bAddDefaults
)
{
DWORD dwReturn = ERROR_SUCCESS;
PSTA_AUTH_METHODS paSingletons[2];
size_t uiNumSingletons = 0;
size_t uiNumRootca = 0;
size_t uiNumAuthMethods = pRuleData->AuthInfos.dwNumAuthInfos;
size_t uiRootIndex = 0;
size_t uiSingletonIndex = 0;
size_t uiNumAuths = 0;
if (pRuleData->bAuthMethodSpecified)
{
pRuleData->dwAuthInfos = uiNumAuthMethods;
pRuleData->AuthInfos.pAuthMethodInfo = new STA_MM_AUTH_METHODS[uiNumAuthMethods];
if(pRuleData->AuthInfos.pAuthMethodInfo == NULL)
{
dwReturn = ERROR_OUTOFMEMORY;
BAIL_OUT;
}
paSingletons[0] = pKerbAuth;
paSingletons[1] = pPskAuth;
// swap if pKerbAuth doesn't exist, or if both exist and sequence is out of order
if (!pKerbAuth || (pPskAuth && (pKerbAuth->pAuthMethodInfo->dwSequence > pPskAuth->pAuthMethodInfo->dwSequence)))
{
paSingletons[0] = pPskAuth;
paSingletons[1] = pKerbAuth;
}
uiNumSingletons = (pKerbAuth ? 1 : 0);
uiNumSingletons += (pPskAuth ? 1 : 0);
uiNumRootca = uiNumAuthMethods - uiNumSingletons;
while (uiSingletonIndex< uiNumSingletons)
{
while ((uiRootIndex < uiNumRootca) && (ppRootcaMMAuth[uiRootIndex]->dwSequence <= paSingletons[uiSingletonIndex]->pAuthMethodInfo->dwSequence))
{
AddAuthMethod(pRuleData, ppRootcaMMAuth[uiRootIndex], &uiNumAuths);
++uiRootIndex;
}
AddAuthMethod(pRuleData, paSingletons[uiSingletonIndex], &uiNumAuths);
++uiSingletonIndex;
}
while (uiRootIndex < uiNumRootca)
{
AddAuthMethod(pRuleData, ppRootcaMMAuth[uiRootIndex], &uiNumAuths);
++uiRootIndex;
}
}
else if (bAddDefaults)
{
DWORD dwLocation=IPSEC_REGISTRY_PROVIDER;
LPTSTR pszMachineName=NULL;
dwReturn = CopyStorageInfo(&pszMachineName,dwLocation);
BAIL_ON_WIN32_ERROR(dwReturn);
PINT_IPSEC_MM_AUTH_INFO pAuthenticationInfo = NULL;
if(dwLocation==IPSEC_REGISTRY_PROVIDER)
{
dwReturn=SmartDefaults(&pAuthenticationInfo, pszMachineName, &(pRuleData->dwAuthInfos), FALSE);
}
else
{
dwReturn=SmartDefaults(&pAuthenticationInfo, NULL, &(pRuleData->dwAuthInfos), TRUE);
}
if(dwReturn==ERROR_SUCCESS)
{
//this conversion is required to get the additional certmap info
//for details , refer the following function
dwReturn = ConvertMMAuthToStaticLocal(pAuthenticationInfo, pRuleData->dwAuthInfos, pRuleData->AuthInfos);
pRuleData->AuthInfos.dwNumAuthInfos = pRuleData->dwAuthInfos;
}
if(pszMachineName)
{
delete [] pszMachineName;
}
}
error:
return dwReturn;
}