added psl_is_cookie_domain_acceptable()

This commit is contained in:
Tim Ruehsen 2014-04-16 10:52:35 +02:00
parent b8f7a79947
commit 2c7c11d8a6
2 changed files with 70 additions and 30 deletions

View File

@ -49,8 +49,12 @@ psl_ctx_t *
psl_load_fp(FILE *fp);
const psl_ctx_t *
psl_builtin(void);
// checks wether domain is a public suffix or not
int
psl_is_public_suffix(const psl_ctx_t *psl, const char *domain);
// checks wether cookie_domain is acceptable for domain or not
int
psl_is_cookie_domain_acceptable(const psl_ctx_t *psl, const char *hostname, const char *cookie_domain);
// returns the longest unregistrable domain within 'domain' or NULL if none found
const char *
psl_unregistrable_domain(const psl_ctx_t *psl, const char *domain);

View File

@ -360,29 +360,20 @@ int psl_is_public_suffix(const psl_ctx_t *psl, const char *domain)
*/
const char *psl_unregistrable_domain(const psl_ctx_t *psl, const char *domain)
{
const char *p, *ret_domain;
if (!psl || !domain)
return NULL;
// We check from right to left, e.g. in www.xxx.org we check org, xxx.org, www.xxx.org in this order
// for being a registered domain.
// We check from left to right to catch special PSL entries like 'forgot.his.name':
// 'forgot.his.name' and 'name' are in the PSL while 'his.name' is not.
if (!(p = strrchr(domain, '.')))
return psl_is_public_suffix(psl, domain) ? domain : NULL;
for (ret_domain = NULL; ;) {
if (!psl_is_public_suffix(psl, p))
return ret_domain;
else if (p == domain)
return domain;
ret_domain = p + 1;
// go left to next dot
while (p > domain && *--p != '.')
;
while (!psl_is_public_suffix(psl, domain)) {
if ((domain = strchr(domain, '.')))
domain++;
else
break; // prevent endless loop if psl_is_public_suffix() is broken.
}
return domain;
}
/**
@ -403,25 +394,23 @@ const char *psl_unregistrable_domain(const psl_ctx_t *psl, const char *domain)
*/
const char *psl_registrable_domain(const psl_ctx_t *psl, const char *domain)
{
const char *p;
int ispublic;
const char *p, *regdom = NULL;
if (!psl || !domain || *domain == '.')
return NULL;
// We check from right to left, e.g. in www.xxx.org we check org, xxx.org, www.xxx.org in this order
// for being a registrable domain.
// We check from left to right to catch special PSL entries like 'forgot.his.name':
// 'forgot.his.name' and 'name' are in the PSL while 'his.name' is not.
if (!(p = strrchr(domain, '.')))
p = domain;
while ((ispublic = psl_is_public_suffix(psl, p)) && p > domain) {
// go left to next dot
while (p > domain && *--p != '.')
;
while (!psl_is_public_suffix(psl, domain)) {
if ((p = strchr(domain, '.'))) {
regdom = domain;
domain = p + 1;
} else
break; // prevent endless loop if psl_is_public_suffix() is broken.
}
return ispublic ? NULL : (*p == '.' ? p + 1 : p);
return regdom;
}
/**
@ -647,3 +636,50 @@ const char *psl_builtin_sha1sum(void)
{
return _psl_sha1_checksum;
}
/**
* psl_is_cookie_domain_acceptable:
* @psl: PSL context pointer
* @hostname: The request hostname.
* @cookie_domain: The domain value from a cookie
*
* This helper function checks whether @cookie_domain is an acceptable cookie domain value for the request
* @hostname.
*
* Returns: 1 if acceptable, 0 if not acceptable.
*
* Since: 0.1
*/
int psl_is_cookie_domain_acceptable(const psl_ctx_t *psl, const char *hostname, const char *cookie_domain)
{
const char *registrable_domain, *p;
size_t hostname_length, cookie_domain_length;
if (!psl || !hostname || !cookie_domain)
return 0;
while (*cookie_domain == '.')
cookie_domain++;
if (!strcmp(hostname, cookie_domain))
return 1; // an exact match is acceptable (and pretty common)
cookie_domain_length = strlen(cookie_domain);
hostname_length = strlen(hostname);
if (cookie_domain_length >= hostname_length)
return 0; // cookie_domain is too long
p = hostname + hostname_length - cookie_domain_length;
if (!strcmp(p, cookie_domain) && p[-1] == '.') {
// OK, cookie_domain matches, but it must be longer than the longest public suffix in 'hostname'
if (!(p = psl_unregistrable_domain(psl, hostname)))
return 1;
if (cookie_domain_length > strlen(p))
return 1;
}
return 0;
}