bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi#include "lib.h"
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi#include "dns-util.h"
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi/**
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi return first position from b->a of c or a if not found
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi */
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomistatic inline
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomiconst char *strchr_ba(const char *a, const char *b, char c)
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi{
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi for(;b>a && *b != c; b--);
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi return b;
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi}
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomiint dns_ncompare(const char *a, const char *b, size_t n)
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi{
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi if (a == NULL && b == NULL) return 0;
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi if (a == NULL && b != NULL) return 1;
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi if (a != NULL && b == NULL) return -1;
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi for(size_t i = 0; i < n &&
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi *a != '\0' &&
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi *b != '\0' &&
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi dns_tolower(*a) == dns_tolower(*b);
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi i++, a++, b++);
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi return dns_tolower(*a) - dns_tolower(*b);
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi}
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomiint dns_compare(const char *a, const char *b)
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi{
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi return dns_ncompare(a, b, (size_t)-1);
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi}
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomiint dns_compare_labels(const char *a, const char *b)
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi{
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi if (a == NULL && b == NULL) return 0;
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi if (a == NULL && b != NULL) return 1;
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi if (a != NULL && b == NULL) return -1;
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi const char *ptr_a = a + strlen(a);
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi const char *ptr_b = b + strlen(b);
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi const char *label_a = ptr_a, *label_b = ptr_b;
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi int comp = 0;
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi while(comp == 0 && ptr_a > a && ptr_b > b) {
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi /* look for start of label, including dot */
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi label_a = strchr_ba(a, ptr_a, '.');
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi label_b = strchr_ba(b, ptr_b, '.');
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi if (ptr_a - label_a != ptr_b - label_b)
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi /* compare labels up to minimum length
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi but include \0 to make sure that we
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi don't consider alpha and alphabet
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi equal */
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi return dns_ncompare(label_a, label_b,
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi I_MIN(ptr_a - label_a,
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi ptr_b - label_b)+1);
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi comp = dns_ncompare(label_a, label_b, ptr_a -label_a);
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi ptr_a = label_a - 1;
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi ptr_b = label_b - 1;
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi }
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi return dns_tolower(*label_a) - dns_tolower(*label_b);
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi}
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomiint dns_match_wildcard(const char *name, const char *mask)
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi{
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi i_assert(name != NULL && mask != NULL);
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi for(;*name != '\0' && *mask != '\0'; name++, mask++) {
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi switch(*mask) {
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi case '*':
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi name = strchr(name, '.');
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi if (name == NULL || mask[1] != '.') return -1;
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi mask++;
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi break;
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi case '?':
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi break;
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi default:
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi if (dns_tolower(*name) != dns_tolower(*mask)) return -1;
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi }
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi }
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi if (*mask == '*') mask++;
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi return dns_tolower(*name) == dns_tolower(*mask) ? 0 : -1;
7cb5a6d1f52abfe2e31f1404cce01ca63daacd17Aki Tuomi}