From 5edc17b7913cac824daa09fca9976c9c19e88822 Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Wed, 11 Oct 2023 17:45:44 +0200
Subject: [PATCH] common: derive alternative host name from its unescaped
 version

Normalization of input makes sure we don't have to deal with special
cases like unescaped dot at the end of label.

Fixes #451 #487
CVE-2023-38473

Reference:https://github.com/lathiat/avahi/commit/b448c9f771bada14ae8de175695a9729f8646797
Conflict:NA

---
 avahi-common/alternative-test.c |  3 +++
 avahi-common/alternative.c      | 27 +++++++++++++++++++--------
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/avahi-common/alternative-test.c b/avahi-common/alternative-test.c
index 9255435ec..681fc15b8 100644
--- a/avahi-common/alternative-test.c
+++ b/avahi-common/alternative-test.c
@@ -31,6 +31,9 @@ int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char *argv[]) {
     const char* const test_strings[] = {
         "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
         "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXüüüüüüü",
+        ").",
+        "\\.",
+        "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\\",
         "gurke",
         "-",
         " #",
diff --git a/avahi-common/alternative.c b/avahi-common/alternative.c
index b3d39f0ed..a094e6d76 100644
--- a/avahi-common/alternative.c
+++ b/avahi-common/alternative.c
@@ -49,15 +49,20 @@ static void drop_incomplete_utf8(char *c) {
 }
 
 char *avahi_alternative_host_name(const char *s) {
+    char label[AVAHI_LABEL_MAX], alternative[AVAHI_LABEL_MAX*4+1];
+    char *alt, *r, *ret;
     const char *e;
-    char *r;
+    size_t len;
 
     assert(s);
 
     if (!avahi_is_valid_host_name(s))
         return NULL;
 
-    if ((e = strrchr(s, '-'))) {
+    if (!avahi_unescape_label(&s, label, sizeof(label)))
+        return NULL;
+
+    if ((e = strrchr(label, '-'))) {
         const char *p;
 
         e++;
@@ -74,19 +79,18 @@ char *avahi_alternative_host_name(const char *s) {
 
     if (e) {
         char *c, *m;
-        size_t l;
         int n;
 
         n = atoi(e)+1;
         if (!(m = avahi_strdup_printf("%i", n)))
             return NULL;
 
-        l = e-s-1;
+        len = e-label-1;
 
-        if (l >= AVAHI_LABEL_MAX-1-strlen(m)-1)
-            l = AVAHI_LABEL_MAX-1-strlen(m)-1;
+        if (len >= AVAHI_LABEL_MAX-1-strlen(m)-1)
+            len = AVAHI_LABEL_MAX-1-strlen(m)-1;
 
-        if (!(c = avahi_strndup(s, l))) {
+        if (!(c = avahi_strndup(label, len))) {
             avahi_free(m);
             return NULL;
         }
@@ -100,7 +104,7 @@ char *avahi_alternative_host_name(const char *s) {
     } else {
         char *c;
 
-        if (!(c = avahi_strndup(s, AVAHI_LABEL_MAX-1-2)))
+        if (!(c = avahi_strndup(label, AVAHI_LABEL_MAX-1-2)))
             return NULL;
 
         drop_incomplete_utf8(c);
@@ -109,6 +113,13 @@ char *avahi_alternative_host_name(const char *s) {
         avahi_free(c);
     }
 
+    alt = alternative;
+    len = sizeof(alternative);
+    ret = avahi_escape_label(r, strlen(r), &alt, &len);
+
+    avahi_free(r);
+    r = avahi_strdup(ret);
+
     assert(avahi_is_valid_host_name(r));
 
     return r;
