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

          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         730 : 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         730 :     static const std::regex generalSyntaxPattern {"[\x20\x09]+"};
      39             : 
      40         730 :     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         730 :                                                 "[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         730 :                                               "([0-9]{1,3})\\;?)?"};
      52             : 
      53             :     // Take each line from the vector
      54             :     // and parse its content
      55             : 
      56         730 :     std::vector<CryptoAttribute> cryptoAttributeVector;
      57             : 
      58        1460 :     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         730 :         std::vector<std::string> sdesLine;
      64         730 :         std::smatch sm_generalSyntaxPattern;
      65             : 
      66         730 :         std::sregex_token_iterator iter(item.begin(), item.end(), generalSyntaxPattern, -1), end;
      67        2919 :         for (; iter != end; ++iter)
      68        2190 :             sdesLine.push_back(*iter);
      69             : 
      70         730 :         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         730 :         std::string tag;
      78         730 :         std::smatch sm_tagPattern;
      79             : 
      80         730 :         if (std::regex_search(sdesLine.at(0), sm_tagPattern, tagPattern)) {
      81         730 :             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         730 :         std::string cryptoSuite;
      91         730 :         std::smatch sm_cryptoSuitePattern;
      92             : 
      93         730 :         if (std::regex_search(sdesLine.at(1), sm_cryptoSuitePattern, cryptoSuitePattern)) {
      94         730 :             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         730 :         std::string srtpKeyInfo;
     104         730 :         std::string srtpKeyMethod;
     105         730 :         std::string lifetime;
     106         730 :         std::string mkiLength;
     107         730 :         std::string mkiValue;
     108         730 :         std::smatch sm_keyParamsPattern;
     109             : 
     110         730 :         if (std::regex_search(sdesLine.at(2), sm_keyParamsPattern, keyParamsPattern)) {
     111         730 :             srtpKeyMethod = sm_keyParamsPattern[1];
     112         730 :             srtpKeyInfo = sm_keyParamsPattern[2];
     113         730 :             lifetime = sm_keyParamsPattern[5];
     114         730 :             mkiValue = sm_keyParamsPattern[6];
     115         730 :             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         730 :         cryptoAttributeVector.emplace_back(std::move(tag),
     123         730 :                                            std::move(cryptoSuite),
     124         730 :                                            std::move(srtpKeyMethod),
     125         730 :                                            std::move(srtpKeyInfo),
     126         730 :                                            std::move(lifetime),
     127         730 :                                            std::move(mkiValue),
     128         730 :                                            std::move(mkiLength));
     129         730 :     }
     130         730 :     return cryptoAttributeVector;
     131           0 : }
     132             : 
     133             : CryptoAttribute
     134         730 : SdesNegotiator::negotiate(const std::vector<std::string>& attributes)
     135             : {
     136             :     try {
     137         730 :         auto cryptoAttributeVector(parse(attributes));
     138         730 :         for (const auto& iter_offer : cryptoAttributeVector) {
     139         730 :             for (const auto& iter_local : CryptoSuites) {
     140         730 :                 if (iter_offer.getCryptoSuite() == iter_local.name)
     141         730 :                     return iter_offer;
     142             :             }
     143             :         }
     144         730 :     } catch (const ParseError& exception) {
     145           0 :         JAMI_WARNING("");
     146           0 :     }
     147           0 :     return {};
     148             : }
     149             : 
     150             : } // namespace jami

Generated by: LCOV version 1.14