LCOV - code coverage report
Current view: top level - src/sip - sdes_negotiator.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 49 56 87.5 %
Date: 2024-04-23 08:02:50 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /*
       2             :  *  Copyright (C) 2004-2024 Savoir-faire Linux Inc.
       3             :  *
       4             :  *  Author: Pierre-Luc Bacon <pierre-luc.bacon@savoirfairelinux.com>
       5             :  *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
       6             :  *  Author: Adrien BĂ©raud <adrien.beraud@savoirfairelinux.com>
       7             :  *  Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com>
       8             :  *
       9             :  *  This program is free software; you can redistribute it and/or modify
      10             :  *  it under the terms of the GNU General Public License as published by
      11             :  *  the Free Software Foundation; either version 3 of the License, or
      12             :  *  (at your option) any later version.
      13             :  *
      14             :  *  This program is distributed in the hope that it will be useful,
      15             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      17             :  *  GNU General Public License for more details.
      18             :  *
      19             :  *  You should have received a copy of the GNU General Public License
      20             :  *  along with this program; if not, write to the Free Software
      21             :  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      22             :  */
      23             : 
      24             : #include "sdes_negotiator.h"
      25             : 
      26             : #include <iostream>
      27             : #include <sstream>
      28             : #include <algorithm>
      29             : #include <stdexcept>
      30             : #include <regex>
      31             : 
      32             : #include <cstdio>
      33             : 
      34             : namespace jami {
      35             : 
      36             : std::vector<CryptoAttribute>
      37         766 : SdesNegotiator::parse(const std::vector<std::string>& attributes)
      38             : {
      39             :     // The patterns below try to follow
      40             :     // the ABNF grammar rules described in
      41             :     // RFC4568 section 9.2 with the general
      42             :     // syntax :
      43             :     // a=crypto:tag 1*WSP crypto-suite 1*WSP key-params *(1*WSP session-param)
      44             : 
      45             :     // used to match white space (which are used as separator)
      46             : 
      47         766 :     static const std::regex generalSyntaxPattern {"[\x20\x09]+"};
      48             : 
      49         766 :     static const std::regex tagPattern {"^([0-9]{1,9})"};
      50             : 
      51             :     static const std::regex cryptoSuitePattern {"(AES_CM_128_HMAC_SHA1_80|"
      52             :                                                 "AES_CM_128_HMAC_SHA1_32|"
      53             :                                                 "F8_128_HMAC_SHA1_80|"
      54         766 :                                                 "[A-Za-z0-9_]+)"}; // srtp-crypto-suite-ext
      55             : 
      56             :     static const std::regex keyParamsPattern {"(inline|[A-Za-z0-9_]+)\\:"
      57             :                                               "([A-Za-z0-9\x2B\x2F\x3D]+)"
      58             :                                               "((\\|2\\^)([0-9]+)\\|"
      59             :                                               "([0-9]+)\\:"
      60         766 :                                               "([0-9]{1,3})\\;?)?"};
      61             : 
      62             :     // Take each line from the vector
      63             :     // and parse its content
      64             : 
      65         766 :     std::vector<CryptoAttribute> cryptoAttributeVector;
      66             : 
      67        1532 :     for (const auto& item : attributes) {
      68             :         // Split the line into its component that we will analyze further down.
      69             :         // Additional white space is added to better split the content
      70             :         // Result is stored in the sdsLine
      71             : 
      72         766 :         std::vector<std::string> sdesLine;
      73         766 :         std::smatch sm_generalSyntaxPattern;
      74             : 
      75         766 :         std::sregex_token_iterator iter(item.begin(), item.end(), generalSyntaxPattern, -1), end;
      76        3064 :         for (; iter != end; ++iter)
      77        2298 :             sdesLine.push_back(*iter);
      78             : 
      79         766 :         if (sdesLine.size() < 3) {
      80           0 :             throw ParseError("Missing components in SDES line");
      81             :         }
      82             : 
      83             :         // Check if the attribute starts with a=crypto
      84             :         // and get the tag for this line
      85             : 
      86         766 :         std::string tag;
      87         766 :         std::smatch sm_tagPattern;
      88             : 
      89         766 :         if (std::regex_search(sdesLine.at(0), sm_tagPattern, tagPattern)) {
      90         766 :             tag = sm_tagPattern[1];
      91             : 
      92             :         } else {
      93           0 :             throw ParseError("No Matching Found in Tag Attribute");
      94             :         }
      95             : 
      96             :         // Check if the crypto suite is valid and retrieve
      97             :         // its value.
      98             : 
      99         766 :         std::string cryptoSuite;
     100         766 :         std::smatch sm_cryptoSuitePattern;
     101             : 
     102         766 :         if (std::regex_search(sdesLine.at(1), sm_cryptoSuitePattern, cryptoSuitePattern)) {
     103         766 :             cryptoSuite = sm_cryptoSuitePattern[1];
     104             : 
     105             :         } else {
     106           0 :             throw ParseError("No Matching Found in CryptoSuite Attribute");
     107             :         }
     108             : 
     109             :         // Parse one or more key-params field.
     110             :         // Group number is used to locate different paras
     111             : 
     112         766 :         std::string srtpKeyInfo;
     113         766 :         std::string srtpKeyMethod;
     114         766 :         std::string lifetime;
     115         766 :         std::string mkiLength;
     116         766 :         std::string mkiValue;
     117         766 :         std::smatch sm_keyParamsPattern;
     118             : 
     119         766 :         if (std::regex_search(sdesLine.at(2), sm_keyParamsPattern, keyParamsPattern)) {
     120         766 :             srtpKeyMethod = sm_keyParamsPattern[1];
     121         766 :             srtpKeyInfo = sm_keyParamsPattern[2];
     122         766 :             lifetime = sm_keyParamsPattern[5];
     123         766 :             mkiValue = sm_keyParamsPattern[6];
     124         766 :             mkiLength = sm_keyParamsPattern[7];
     125             : 
     126             :         } else {
     127           0 :             throw ParseError("No Matching Found in Key-params Attribute");
     128             :         }
     129             : 
     130             :         // Add the new CryptoAttribute to the vector
     131         766 :         cryptoAttributeVector.emplace_back(std::move(tag),
     132         766 :                                            std::move(cryptoSuite),
     133         766 :                                            std::move(srtpKeyMethod),
     134         766 :                                            std::move(srtpKeyInfo),
     135         766 :                                            std::move(lifetime),
     136         766 :                                            std::move(mkiValue),
     137         766 :                                            std::move(mkiLength));
     138         766 :     }
     139         766 :     return cryptoAttributeVector;
     140           0 : }
     141             : 
     142             : CryptoAttribute
     143         766 : SdesNegotiator::negotiate(const std::vector<std::string>& attributes)
     144             : {
     145             :     try {
     146         766 :         auto cryptoAttributeVector(parse(attributes));
     147         766 :         for (const auto& iter_offer : cryptoAttributeVector) {
     148         766 :             for (const auto& iter_local : CryptoSuites) {
     149         766 :                 if (iter_offer.getCryptoSuite() == iter_local.name)
     150         766 :                     return iter_offer;
     151             :             }
     152             :         }
     153         766 :     } catch (const ParseError& exception) {
     154           0 :     }
     155           0 :     return {};
     156             : }
     157             : 
     158             : } // namespace jami

Generated by: LCOV version 1.14