@@ -33,11 +33,6 @@ inline bool match_prefix(string_view str, string_view prefix) {
33
33
std::mismatch (prefix.begin (), prefix.end (), str.begin ()).first == prefix.end ();
34
34
}
35
35
36
- inline void trim_begin (string &str) {
37
- str.erase (str.begin (),
38
- std::find_if (str.begin (), str.end (), [](char c) { return !std::isspace (c); }));
39
- }
40
-
41
36
inline void trim_end (string &str) {
42
37
str.erase (
43
38
std::find_if (str.rbegin (), str.rend (), [](char c) { return !std::isspace (c); }).base (),
@@ -71,22 +66,6 @@ template <typename T> T to_integer(string_view s) {
71
66
}
72
67
}
73
68
74
- inline bool is_sha256_fingerprint (string_view f) {
75
- if (f.size () != 32 * 3 - 1 )
76
- return false ;
77
-
78
- for (size_t i = 0 ; i < f.size (); ++i) {
79
- if (i % 3 == 2 ) {
80
- if (f[i] != ' :' )
81
- return false ;
82
- } else {
83
- if (!std::isxdigit (f[i]))
84
- return false ;
85
- }
86
- }
87
- return true ;
88
- }
89
-
90
69
} // namespace
91
70
92
71
namespace rtc {
@@ -131,12 +110,35 @@ Description::Description(const string &sdp, Type type, Role role)
131
110
// media-level SDP attribute. If it is a session-level attribute, it applies to all
132
111
// TLS sessions for which no media-level fingerprint attribute is defined.
133
112
if (!mFingerprint || index == 0 ) { // first media overrides session-level
134
- if (match_prefix (value, " sha-256 " ) || match_prefix (value, " SHA-256 " )) {
135
- string fingerprint{value.substr (8 )};
136
- trim_begin (fingerprint);
137
- setFingerprint (std::move (fingerprint));
138
- } else {
113
+ auto fingerprintExploded = utils::explode (string (value), ' ' );
114
+ if (fingerprintExploded.size () != 2 ) {
139
115
PLOG_WARNING << " Unknown SDP fingerprint format: " << value;
116
+ continue ;
117
+ }
118
+
119
+ auto first = fingerprintExploded.at (0 );
120
+ std::transform (first.begin (), first.end (), first.begin (),
121
+ [](char c) { return char (std::tolower (c)); });
122
+
123
+ std::optional<CertificateFingerprint::Algorithm> fingerprintAlgorithm;
124
+
125
+ for (auto a : std::array<CertificateFingerprint::Algorithm, 5 >{
126
+ CertificateFingerprint::Algorithm::Sha1,
127
+ CertificateFingerprint::Algorithm::Sha224,
128
+ CertificateFingerprint::Algorithm::Sha256,
129
+ CertificateFingerprint::Algorithm::Sha384,
130
+ CertificateFingerprint::Algorithm::Sha512}) {
131
+ if (first == CertificateFingerprint::AlgorithmIdentifier (a)) {
132
+ fingerprintAlgorithm = a;
133
+ break ;
134
+ }
135
+ }
136
+
137
+ if (fingerprintAlgorithm.has_value ()) {
138
+ setFingerprint (CertificateFingerprint{
139
+ fingerprintAlgorithm.value (), std::move (fingerprintExploded.at (1 ))});
140
+ } else {
141
+ PLOG_WARNING << " Unknown certificate fingerprint algorithm: " << first;
140
142
}
141
143
}
142
144
} else if (key == " ice-ufrag" ) {
@@ -205,7 +207,7 @@ std::vector<string> Description::iceOptions() const { return mIceOptions; }
205
207
206
208
optional<string> Description::icePwd () const { return mIcePwd ; }
207
209
208
- optional<string > Description::fingerprint () const { return mFingerprint ; }
210
+ optional<CertificateFingerprint > Description::fingerprint () const { return mFingerprint ; }
209
211
210
212
bool Description::ended () const { return mEnded ; }
211
213
@@ -214,13 +216,13 @@ void Description::hintType(Type type) {
214
216
mType = type;
215
217
}
216
218
217
- void Description::setFingerprint (string fingerprint ) {
218
- if (!is_sha256_fingerprint (fingerprint ))
219
- throw std::invalid_argument (" Invalid SHA256 fingerprint \" " + fingerprint + " \" " );
219
+ void Description::setFingerprint (CertificateFingerprint f ) {
220
+ if (!f. isValid ( ))
221
+ throw std::invalid_argument (" Invalid " + CertificateFingerprint::AlgorithmIdentifier (f. algorithm ) + " fingerprint \" " + f. value + " \" " );
220
222
221
- std::transform (fingerprint. begin (), fingerprint. end (), fingerprint .begin (),
223
+ std::transform (f. value . begin (), f. value . end (), f. value .begin (),
222
224
[](char c) { return char (std::toupper (c)); });
223
- mFingerprint . emplace ( std::move (fingerprint) );
225
+ mFingerprint = std::move (f );
224
226
}
225
227
226
228
void Description::addIceOption (string option) {
@@ -315,7 +317,9 @@ string Description::generateSdp(string_view eol) const {
315
317
if (!mIceOptions .empty ())
316
318
sdp << " a=ice-options:" << utils::implode (mIceOptions , ' ,' ) << eol;
317
319
if (mFingerprint )
318
- sdp << " a=fingerprint:sha-256 " << *mFingerprint << eol;
320
+ sdp << " a=fingerprint:"
321
+ << CertificateFingerprint::AlgorithmIdentifier (mFingerprint ->algorithm ) << " "
322
+ << mFingerprint ->value << eol;
319
323
320
324
for (const auto &attr : mAttributes )
321
325
sdp << " a=" << attr << eol;
@@ -378,7 +382,9 @@ string Description::generateApplicationSdp(string_view eol) const {
378
382
if (!mIceOptions .empty ())
379
383
sdp << " a=ice-options:" << utils::implode (mIceOptions , ' ,' ) << eol;
380
384
if (mFingerprint )
381
- sdp << " a=fingerprint:sha-256 " << *mFingerprint << eol;
385
+ sdp << " a=fingerprint:"
386
+ << CertificateFingerprint::AlgorithmIdentifier (mFingerprint ->algorithm ) << " "
387
+ << mFingerprint ->value << eol;
382
388
383
389
for (const auto &attr : mAttributes )
384
390
sdp << " a=" << attr << eol;
@@ -876,8 +882,7 @@ void Description::Application::parseSdpLine(string_view line) {
876
882
}
877
883
}
878
884
879
- Description::Media::Media (const string &sdp)
880
- : Entry(get_first_line(sdp), " " , Direction::Unknown) {
885
+ Description::Media::Media (const string &sdp) : Entry(get_first_line(sdp), " " , Direction::Unknown) {
881
886
string line;
882
887
std::istringstream ss (sdp);
883
888
std::getline (ss, line); // discard first line
@@ -1288,6 +1293,60 @@ string Description::typeToString(Type type) {
1288
1293
}
1289
1294
}
1290
1295
1296
+ size_t
1297
+ CertificateFingerprint::AlgorithmSize (CertificateFingerprint::Algorithm fingerprintAlgorithm) {
1298
+ switch (fingerprintAlgorithm) {
1299
+ case CertificateFingerprint::Algorithm::Sha1:
1300
+ return 20 ;
1301
+ case CertificateFingerprint::Algorithm::Sha224:
1302
+ return 28 ;
1303
+ case CertificateFingerprint::Algorithm::Sha256:
1304
+ return 32 ;
1305
+ case CertificateFingerprint::Algorithm::Sha384:
1306
+ return 48 ;
1307
+ case CertificateFingerprint::Algorithm::Sha512:
1308
+ return 64 ;
1309
+ default :
1310
+ return 0 ;
1311
+ }
1312
+ }
1313
+
1314
+ std::string CertificateFingerprint::AlgorithmIdentifier (
1315
+ CertificateFingerprint::Algorithm fingerprintAlgorithm) {
1316
+ switch (fingerprintAlgorithm) {
1317
+ case CertificateFingerprint::Algorithm::Sha1:
1318
+ return " sha-1" ;
1319
+ case CertificateFingerprint::Algorithm::Sha224:
1320
+ return " sha-224" ;
1321
+ case CertificateFingerprint::Algorithm::Sha256:
1322
+ return " sha-256" ;
1323
+ case CertificateFingerprint::Algorithm::Sha384:
1324
+ return " sha-256" ;
1325
+ case CertificateFingerprint::Algorithm::Sha512:
1326
+ return " sha-512" ;
1327
+ default :
1328
+ return " unknown" ;
1329
+ }
1330
+ }
1331
+
1332
+ bool CertificateFingerprint::isValid () const {
1333
+ size_t expectedSize = AlgorithmSize (this ->algorithm );
1334
+ if (expectedSize == 0 || this ->value .size () != expectedSize * 3 - 1 ) {
1335
+ return false ;
1336
+ }
1337
+
1338
+ for (size_t i = 0 ; i < this ->value .size (); ++i) {
1339
+ if (i % 3 == 2 ) {
1340
+ if (this ->value [i] != ' :' )
1341
+ return false ;
1342
+ } else {
1343
+ if (!std::isxdigit (this ->value [i]))
1344
+ return false ;
1345
+ }
1346
+ }
1347
+ return true ;
1348
+ }
1349
+
1291
1350
} // namespace rtc
1292
1351
1293
1352
std::ostream &operator <<(std::ostream &out, const rtc::Description &description) {
0 commit comments