Skip to content

Commit fcf9c0d

Browse files
committed
Verify domain name in WiFiClientSecure::verify
1 parent e206093 commit fcf9c0d

File tree

2 files changed

+47
-4
lines changed

2 files changed

+47
-4
lines changed

libraries/ESP8266WiFi/src/WiFiClientSecure.cpp

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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

388431
void WiFiClientSecure::setCertificate(const uint8_t* cert_data, size_t size) {

libraries/ESP8266WiFi/src/WiFiClientSecure.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class WiFiClientSecure : public WiFiClient {
3838
int connect(IPAddress ip, uint16_t port) override;
3939
int connect(const char* name, uint16_t port) override;
4040

41-
bool verify(const char* fingerprint, const char* url);
41+
bool verify(const char* fingerprint, const char* domain_name);
4242

4343
uint8_t connected() override;
4444
size_t write(const uint8_t *buf, size_t size) override;

0 commit comments

Comments
 (0)