@@ -352,7 +352,33 @@ static bool parseHexNibble(char pb, uint8_t* res) {
352352 return false ;
353353}
354354
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) {
356382 if (!_ssl)
357383 return false ;
358384
@@ -380,9 +406,26 @@ bool WiFiClientSecure::verify(const char* fp, const char* url) {
380406 return false ;
381407 }
382408
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 ();
384412
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 ;
386429}
387430
388431void WiFiClientSecure::setCertificate (const uint8_t * cert_data, size_t size) {
0 commit comments