LCOV - code coverage report
Current view: top level - src/sip - sdes_negotiator.cpp (source / functions) Coverage Total Hit
Test: jami-coverage-filtered.info Lines: 86.0 % 57 49
Test Date: 2026-06-13 09:18:46 Functions: 50.0 % 4 2

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

Generated by: LCOV version 2.0-1