mirror of
https://git.jami.net/savoirfairelinux/jami-daemon.git
synced 2025-08-12 22:09:25 +08:00
[#1744] Integrating some of the needed regular expression patterns in order
to parse the attribute line as defined in RFC4568. Still need to support multiple inline: fields and multiple session-params. Added testing file for the SdesNegotiator class. Still need to write proper unit tests.
This commit is contained in:
@ -18,7 +18,7 @@
|
||||
|
||||
#include "SdesNegotiator.h"
|
||||
|
||||
#include "regex.h"
|
||||
#include "Regex.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
@ -34,134 +34,119 @@ namespace sfl {
|
||||
std::string sessionParams;
|
||||
};
|
||||
|
||||
SdesNegotiator::SdesNegotiator(const std::vector<CryptoSuiteDefinition>& localCapabilites, const std::vector<std::string>& remoteAttribute) :
|
||||
SdesNegotiator::SdesNegotiator(const std::vector<CryptoSuiteDefinition>& localCapabilites,
|
||||
const std::vector<std::string>& remoteAttribute) :
|
||||
_remoteAttribute(remoteAttribute),
|
||||
_localCapabilities(localCapabilites)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CryptoAttribute * SdesNegotiator::tokenize(const std::string& attributeLine)
|
||||
{
|
||||
// Split the line into at most
|
||||
// 4 components corresponding to
|
||||
// a=crypto:<tag> <crypto-suite> <key-params> [<session-params>]
|
||||
size_t pos;
|
||||
const char WSP = ' ';
|
||||
std::string line(attributeLine);
|
||||
|
||||
pos = line.rfind(WSP);
|
||||
|
||||
std::string token;
|
||||
std::vector<std::string> lineSplitted;
|
||||
|
||||
while (pos != std::string::npos && lineSplitted.size() != 4) {
|
||||
|
||||
token = line.substr(pos+1);
|
||||
lineSplitted.push_back(token);
|
||||
|
||||
token = line.substr(0, pos);
|
||||
line = token;
|
||||
|
||||
pos = line.rfind(WSP);
|
||||
|
||||
}
|
||||
|
||||
lineSplitted.push_back(line);
|
||||
|
||||
CryptoAttribute * cryptoLine;
|
||||
// Build up the new CryptoAttribute
|
||||
try {
|
||||
cryptoLine = new CryptoAttribute();
|
||||
} catch (std::bad_alloc&) {
|
||||
std::cerr << "Failed create new CryptoLine" << std::endl;
|
||||
throw;
|
||||
}
|
||||
|
||||
std::reverse(lineSplitted.begin(), lineSplitted.end());
|
||||
|
||||
cryptoLine->tag = lineSplitted.at(0);
|
||||
cryptoLine->cryptoSuite = lineSplitted.at(1);
|
||||
cryptoLine->keyParams = lineSplitted.at(2);
|
||||
if (lineSplitted.size() == 4) {
|
||||
cryptoLine->sessionParams = lineSplitted.at(3);
|
||||
}
|
||||
|
||||
return cryptoLine;
|
||||
}
|
||||
|
||||
bool SdesNegotiator::parse(void)
|
||||
{
|
||||
std::vector<std::string>::iterator iter;
|
||||
|
||||
for (iter = _remoteAttribute.begin(); iter != _remoteAttribute.end(); iter++) {
|
||||
|
||||
// Split the line into components
|
||||
// and build up a CryptoAttribute
|
||||
// structure.
|
||||
CryptoAttribute * cryptoLine;
|
||||
void SdesNegotiator::parse(void)
|
||||
{
|
||||
// The patterns below try to follow
|
||||
// the ABNF grammar rules described in
|
||||
// RFC4568 section 9.2 with the general
|
||||
// syntax :
|
||||
//a=crypto:tag 1*WSP crypto-suite 1*WSP key-params *(1*WSP session-param)
|
||||
|
||||
Regex tagPattern, cryptoSuitePattern, keyParamsPattern, sessionParamPattern;
|
||||
|
||||
try {
|
||||
tagPattern = "^a=crypto:(?P<tag>[0-9]{1,9})";
|
||||
|
||||
cryptoSuitePattern = "[\x20\x09]+(?P<cryptoSuite>AES_CM_128_HMAC_SHA1_80|" \
|
||||
"AES_CM_128_HMAC_SHA1_32|" \
|
||||
"F8_128_HMAC_SHA1_80|" \
|
||||
"[A-Za-z0-9_]+)"; // srtp-crypto-suite-ext
|
||||
|
||||
keyParamsPattern = "[\x20\x09]+(?P<srtpKeyMethod>inline|[A-Za-z0-9_]+)\\:" \
|
||||
"(?P<srtpKeyInfo>[A-Za-z0-9\x2B\x2F\x3D]+)\\|" \
|
||||
"2\\^(?P<lifetime>[0-9]+)\\|" \
|
||||
"(?P<mkiValue>[0-9]+)\\:" \
|
||||
"(?P<mkiLength>[0-9]{1,3})\\;?";
|
||||
|
||||
sessionParamPattern = "[\x20\x09]+(?P<sessionParam>(kdr\\=[0-9]{1,2}|" \
|
||||
"UNENCRYPTED_SRTP|" \
|
||||
"UNENCRYPTED_SRTCP|" \
|
||||
"UNAUTHENTICATED_SRTP|" \
|
||||
"FEC_ORDER=(?P<fecOrder>FEC_SRTP|SRTP_FEC)|" \
|
||||
"FEC_KEY=(?P<fecKey>" + keyParamsPattern.getPattern() + ")|" \
|
||||
"WSH=(?P<wsh>[0-9]{1,2})|" \
|
||||
"(?<!\\-)[[:graph:]]+))*"; // srtp-session-extension
|
||||
|
||||
} catch(compile_error& exception) {
|
||||
throw parse_error("A compile exception occured on a pattern.");
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Take each line from the vector
|
||||
// and parse its content
|
||||
|
||||
std::vector<std::string>::iterator iter;
|
||||
for (iter = _remoteAttribute.begin(); iter != _remoteAttribute.end(); iter++) {
|
||||
|
||||
std::cout << (*iter) << std::endl;
|
||||
|
||||
// Check if the attribute
|
||||
// starts with a=crypto
|
||||
// and get the tag for this line
|
||||
tagPattern << (*iter);
|
||||
try {
|
||||
cryptoLine = tokenize((*iter));
|
||||
} catch (...) {
|
||||
std::cerr << "An exception occured" << std::endl;
|
||||
}
|
||||
std::string tag = tagPattern.group("tag");
|
||||
std::cout << "tag = " << tag << std::endl;
|
||||
} catch (match_error& exception) {
|
||||
throw parse_error("Error while parsing the tag field");
|
||||
}
|
||||
|
||||
// Check if the crypto
|
||||
// suite is valid and retreive
|
||||
// its value.
|
||||
cryptoSuitePattern << (*iter);
|
||||
try {
|
||||
std::string cryptoSuite = cryptoSuitePattern.group("cryptoSuite");
|
||||
std::cout << "crypto-suite = " << cryptoSuite << std::endl;
|
||||
} catch (match_error& exception) {
|
||||
throw parse_error("Error while parsing the crypto-suite field");
|
||||
}
|
||||
|
||||
// Parse one or more key-params
|
||||
// field.
|
||||
keyParamsPattern << (*iter);
|
||||
try {
|
||||
std::string srtpKeyMethod = keyParamsPattern.group("srtpKeyMethod");
|
||||
std::cout << "srtp-key-method = " << srtpKeyMethod << std::endl;
|
||||
|
||||
std::string srtpKeyInfo = keyParamsPattern.group("srtpKeyInfo");
|
||||
std::cout << "srtp-key-info = " << srtpKeyInfo << std::endl;
|
||||
|
||||
std::string lifetime = keyParamsPattern.group("lifetime");
|
||||
std::cout << "lifetime = " << lifetime << std::endl;
|
||||
|
||||
std::string mkiValue = keyParamsPattern.group("mkiValue");
|
||||
std::cout << "mkiValue = " << mkiValue << std::endl;
|
||||
|
||||
std::string mkiLength = keyParamsPattern.group("mkiLength");
|
||||
std::cout << "mkiLength = " << mkiLength << std::endl;
|
||||
|
||||
} catch (match_error& exception) {
|
||||
throw parse_error("Error while parsing the key-params field");
|
||||
}
|
||||
|
||||
// Parse the optional session-param
|
||||
// field
|
||||
sessionParamPattern << (*iter);
|
||||
try {
|
||||
std::string sessionParam = sessionParamPattern.group("sessionParam");
|
||||
std::cout << "srtp-session-param = " << sessionParam << std::endl;
|
||||
} catch (not_found& exception){
|
||||
// Thats totally find, do nothing
|
||||
} catch (match_error& exception) {
|
||||
throw parse_error("Error while parsing the crypto-suite field");
|
||||
}
|
||||
|
||||
// Check if we have the right kind of attribute
|
||||
if (cryptoLine->tag.find("a=crypto:") != 0) {
|
||||
std::cout << cryptoLine->tag << std::endl;
|
||||
throw std::runtime_error("Bad syntax");
|
||||
}
|
||||
|
||||
// Find index
|
||||
size_t tagPos;
|
||||
tagPos = cryptoLine->tag.find(":");
|
||||
if (tagPos == std::string::npos) {
|
||||
throw std::runtime_error("Bad syntax");
|
||||
}
|
||||
|
||||
std::string index;
|
||||
index = cryptoLine->tag.substr(tagPos+1);
|
||||
|
||||
std::cout << "index:" << index << std::endl;
|
||||
// Make sure its less than 9 digit long
|
||||
|
||||
if (index.length() > 9) {
|
||||
throw std::runtime_error("Index too long.");
|
||||
}
|
||||
|
||||
int tagIndex;
|
||||
std::istringstream ss(index);
|
||||
ss >> tagIndex;
|
||||
if (ss.fail()) {
|
||||
throw std::runtime_error("Bad conversion");
|
||||
}
|
||||
|
||||
// Check if the given crypto-suite is valid
|
||||
// by looking in our list.
|
||||
// Extension: 1*(ALPHA / DIGIT / "_")
|
||||
int i;
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (cryptoLine->cryptoSuite.compare(CryptoSuites[i].name) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 3) {
|
||||
std::cout << "This is an unhandled extension\n" << std::endl;
|
||||
}
|
||||
|
||||
// Parse the key-params
|
||||
// Check it starts with a valid key-method
|
||||
if (cryptoLine->keyParams.find("inline:") != 0) {
|
||||
throw std::runtime_error("Unsupported key-method\n");
|
||||
}
|
||||
|
||||
KeyMethod method = Inline;
|
||||
|
||||
// Find concatenated key and salt values
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user