#include "../curl_setup.h"
#if defined(USE_OPENSSL) || defined(USE_SCHANNEL)
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETINET_IN6_H
#include <netinet/in6.h>
#endif
#include "../curl_memrchr.h"
#include "hostcheck.h"
#include "../hostip.h"
#include "../curl_memory.h"
#include "../memdebug.h"
static bool pmatch(const char *hostname, size_t hostlen,
const char *pattern, size_t patternlen)
{
if(hostlen != patternlen)
return FALSE;
return curl_strnequal(hostname, pattern, hostlen);
}
static bool hostmatch(const char *hostname,
size_t hostlen,
const char *pattern,
size_t patternlen)
{
const char *pattern_label_end;
DEBUGASSERT(pattern);
DEBUGASSERT(patternlen);
DEBUGASSERT(hostname);
DEBUGASSERT(hostlen);
if(hostname[hostlen-1]=='.')
hostlen--;
if(pattern[patternlen-1]=='.')
patternlen--;
if(strncmp(pattern, "*.", 2))
return pmatch(hostname, hostlen, pattern, patternlen);
else if(Curl_host_is_ipnum(hostname))
return FALSE;
pattern_label_end = memchr(pattern, '.', patternlen);
if(!pattern_label_end ||
(memrchr(pattern, '.', patternlen) == pattern_label_end))
return pmatch(hostname, hostlen, pattern, patternlen);
else {
const char *hostname_label_end = memchr(hostname, '.', hostlen);
if(hostname_label_end) {
size_t skiphost = hostname_label_end - hostname;
size_t skiplen = pattern_label_end - pattern;
return pmatch(hostname_label_end, hostlen - skiphost,
pattern_label_end, patternlen - skiplen);
}
}
return FALSE;
}
bool Curl_cert_hostcheck(const char *match, size_t matchlen,
const char *hostname, size_t hostlen)
{
if(match && *match && hostname && *hostname)
return hostmatch(hostname, hostlen, match, matchlen);
return FALSE;
}
#endif