summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-11-20 17:52:36 +0100
committerLennart Poettering <lennart@poettering.net>2015-11-23 21:31:28 +0100
commit0a49b6b6dce3a756bd8c4d458a34c2d8035ae99d (patch)
tree5d898be726a9560f44184a9d0af43d7de2c09cd7 /src/shared
parente429762faaac0c49353d35144a9d45d283e91213 (diff)
dns-domain: add code for verifying validity of DNS-SD service names and types
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/dns-domain.c67
-rw-r--r--src/shared/dns-domain.h4
2 files changed, 71 insertions, 0 deletions
diff --git a/src/shared/dns-domain.c b/src/shared/dns-domain.c
index 423ccca9cc..014e0bd70d 100644
--- a/src/shared/dns-domain.c
+++ b/src/shared/dns-domain.c
@@ -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;
+}
diff --git a/src/shared/dns-domain.h b/src/shared/dns-domain.h
index b214897440..22c394443b 100644
--- a/src/shared/dns-domain.h
+++ b/src/shared/dns-domain.h
@@ -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);