dns-domain: add code for verifying validity of DNS-SD service names and types
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
#include "hexdecoct.h"
|
||||
#include "parse-util.h"
|
||||
#include "string-util.h"
|
||||
#include "utf8.h"
|
||||
|
||||
int dns_label_unescape(const char **name, char *dest, size_t sz) {
|
||||
const char *n;
|
||||
@@ -749,3 +750,69 @@ int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len) {
|
||||
|
||||
return out - buffer;
|
||||
}
|
||||
|
||||
int dns_srv_type_verify(const char *name) {
|
||||
unsigned c = 0;
|
||||
int r;
|
||||
|
||||
if (!name)
|
||||
return 0;
|
||||
|
||||
for (;;) {
|
||||
char label[DNS_LABEL_MAX];
|
||||
int k;
|
||||
|
||||
/* This more or less implements RFC 6335, Section 5.1 */
|
||||
|
||||
r = dns_label_unescape(&name, label, sizeof(label));
|
||||
if (r == -EINVAL)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return c >= 2; /* At least two labels */
|
||||
if (r < 2) /* Label needs to be at least 2 chars long */
|
||||
return 0;
|
||||
if (label[0] != '_') /* First label char needs to be underscore */
|
||||
return 0;
|
||||
|
||||
/* Second char must be a letter */
|
||||
if (!(label[1] >= 'A' && label[1] <= 'Z') &&
|
||||
!(label[1] >= 'a' && label[1] <= 'z'))
|
||||
return 0;
|
||||
|
||||
/* Third and further chars must be alphanumeric or a hyphen */
|
||||
for (k = 2; k < r; k++) {
|
||||
if (!(label[k] >= 'A' && label[k] <= 'Z') &&
|
||||
!(label[k] >= 'a' && label[k] <= 'z') &&
|
||||
!(label[k] >= '0' && label[k] <= '9') &&
|
||||
label[k] != '-')
|
||||
return 0;
|
||||
}
|
||||
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
bool dns_service_name_is_valid(const char *name) {
|
||||
size_t l;
|
||||
|
||||
/* This more or less implements RFC 6763, Section 4.1.1 */
|
||||
|
||||
if (!name)
|
||||
return false;
|
||||
|
||||
if (!utf8_is_valid(name))
|
||||
return false;
|
||||
|
||||
if (string_has_cc(name, NULL))
|
||||
return false;
|
||||
|
||||
l = strlen(name);
|
||||
if (l <= 0)
|
||||
return false;
|
||||
if (l > 63)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -69,3 +69,7 @@ int dns_name_root(const char *name);
|
||||
int dns_name_single_label(const char *name);
|
||||
|
||||
int dns_name_to_wire_format(const char *domain, uint8_t *buffer, size_t len);
|
||||
|
||||
int dns_srv_type_verify(const char *name);
|
||||
|
||||
bool dns_service_name_is_valid(const char *name);
|
||||
|
||||
@@ -316,6 +316,40 @@ static void test_dns_name_is_valid(void) {
|
||||
test_dns_name_is_valid_one("\n", 0);
|
||||
}
|
||||
|
||||
static void test_dns_service_name_is_valid(void) {
|
||||
assert_se(dns_service_name_is_valid("Lennart's Compüter"));
|
||||
assert_se(dns_service_name_is_valid("piff.paff"));
|
||||
|
||||
assert_se(!dns_service_name_is_valid(NULL));
|
||||
assert_se(!dns_service_name_is_valid(""));
|
||||
assert_se(!dns_service_name_is_valid("foo\nbar"));
|
||||
assert_se(!dns_service_name_is_valid("foo\201bar"));
|
||||
assert_se(!dns_service_name_is_valid("this is an overly long string that is certainly longer than 63 characters"));
|
||||
}
|
||||
|
||||
static void test_dns_srv_type_verify(void) {
|
||||
|
||||
assert_se(dns_srv_type_verify("_http._tcp") > 0);
|
||||
assert_se(dns_srv_type_verify("_foo-bar._tcp") > 0);
|
||||
assert_se(dns_srv_type_verify("_w._udp") > 0);
|
||||
assert_se(dns_srv_type_verify("_piep._sub._w._udp") > 0);
|
||||
assert_se(dns_srv_type_verify("_a800._tcp") > 0);
|
||||
assert_se(dns_srv_type_verify("_a-800._tcp") > 0);
|
||||
|
||||
assert_se(dns_srv_type_verify(NULL) == 0);
|
||||
assert_se(dns_srv_type_verify("") == 0);
|
||||
assert_se(dns_srv_type_verify("x") == 0);
|
||||
assert_se(dns_srv_type_verify("_foo") == 0);
|
||||
assert_se(dns_srv_type_verify("_tcp") == 0);
|
||||
assert_se(dns_srv_type_verify("_") == 0);
|
||||
assert_se(dns_srv_type_verify("_foo.") == 0);
|
||||
assert_se(dns_srv_type_verify("_föo._tcp") == 0);
|
||||
assert_se(dns_srv_type_verify("_f\no._tcp") == 0);
|
||||
assert_se(dns_srv_type_verify("_800._tcp") == 0);
|
||||
assert_se(dns_srv_type_verify("_-800._tcp") == 0);
|
||||
assert_se(dns_srv_type_verify("_-foo._tcp") == 0);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
test_dns_label_unescape();
|
||||
@@ -331,6 +365,8 @@ int main(int argc, char *argv[]) {
|
||||
test_dns_name_concat();
|
||||
test_dns_name_is_valid();
|
||||
test_dns_name_to_wire_format();
|
||||
test_dns_service_name_is_valid();
|
||||
test_dns_srv_type_verify();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user