////////////////////////////////////////////////////////////////////////////// // 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; }