@@ -352,7 +352,33 @@ static bool parseHexNibble(char pb, uint8_t* res) {
352
352
return false ;
353
353
}
354
354
355
- bool WiFiClientSecure::verify (const char * fp, const char * url) {
355
+ // Compare a name from certificate and domain name, return true if they match
356
+ static bool matchName (const String& name, const String& domainName)
357
+ {
358
+ int wildcardPos = name.indexOf (' *' );
359
+ if (wildcardPos == -1 ) {
360
+ // Not a wildcard, expect an exact match
361
+ return name == domainName;
362
+ }
363
+ int firstDotPos = name.indexOf (' .' );
364
+ if (wildcardPos > firstDotPos) {
365
+ // Wildcard is not part of leftmost component of domain name
366
+ // Do not attempt to match (rfc6125 6.4.3.1)
367
+ return false ;
368
+ }
369
+ if (wildcardPos != 0 || firstDotPos != 1 ) {
370
+ // Matching of wildcards such as baz*.example.com and b*z.example.com
371
+ // is optional. Maybe implement this in the future?
372
+ return false ;
373
+ }
374
+ int domainNameFirstDotPos = domainName.indexOf (' .' );
375
+ if (domainNameFirstDotPos < 0 ) {
376
+ return false ;
377
+ }
378
+ return domainName.substring (domainNameFirstDotPos) == name.substring (firstDotPos);
379
+ }
380
+
381
+ bool WiFiClientSecure::verify (const char * fp, const char * domain_name) {
356
382
if (!_ssl)
357
383
return false ;
358
384
@@ -380,9 +406,26 @@ bool WiFiClientSecure::verify(const char* fp, const char* url) {
380
406
return false ;
381
407
}
382
408
383
- // TODO: check URL against certificate
409
+ DEBUGV (" domain name: '%s'\r\n " , (domain_name)?domain_name:" (null)" );
410
+ String domain_name_str (domain_name);
411
+ domain_name_str.toLowerCase ();
384
412
385
- return true ;
413
+ const char * san = NULL ;
414
+ int i = 0 ;
415
+ while ((san = ssl_get_cert_subject_alt_dnsname (*_ssl, i)) != NULL ) {
416
+ if (matchName (String (san), domain_name_str)) {
417
+ return true ;
418
+ }
419
+ DEBUGV (" SAN %d: '%s', no match\r\n " , i, san);
420
+ ++i;
421
+ }
422
+ const char * common_name = ssl_get_cert_dn (*_ssl, SSL_X509_CERT_COMMON_NAME);
423
+ if (common_name && matchName (String (common_name), domain_name_str)) {
424
+ return true ;
425
+ }
426
+ DEBUGV (" CN: '%s', no match\r\n " , (common_name)?common_name:" (null)" );
427
+
428
+ return false ;
386
429
}
387
430
388
431
void WiFiClientSecure::setCertificate (const uint8_t * cert_data, size_t size) {
0 commit comments