Skip to content

Commit 0894e87

Browse files
committed
Merge remote-tracking branch 'evolvis/dns-things'
2 parents ca958dc + 0f822af commit 0894e87

File tree

4 files changed

+70
-137
lines changed

4 files changed

+70
-137
lines changed

libc/inet/Makefile.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ CSRC-$(V4_OR_V6) += \
2626
inet_lnaof.c inet_netof.c
2727
# multi source resolv.c
2828
CSRC-$(V4_OR_V6) += \
29-
encodeh.c decodeh.c encoded.c decoded.c \
29+
encodeh.c decodeh.c \
3030
encodeq.c encodea.c \
3131
read_etc_hosts_r.c \
3232
dnslookup.c opennameservers.c closenameservers.c \

libc/inet/decoded.c

Lines changed: 0 additions & 8 deletions
This file was deleted.

libc/inet/encoded.c

Lines changed: 0 additions & 8 deletions
This file was deleted.

libc/inet/resolv.c

Lines changed: 69 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
/*
1212
* Portions Copyright (c) 1985, 1993
1313
* The Regents of the University of California. All rights reserved.
14+
* Portions Copyright © 2021 mirabilos <m@mirbsd.org>
1415
*
1516
* Redistribution and use in source and binary forms, with or without
1617
* modification, are permitted provided that the following conditions
@@ -395,14 +396,6 @@ extern int __dns_lookup(const char *name,
395396
int type,
396397
unsigned char **outpacket,
397398
struct resolv_answer *a) attribute_hidden;
398-
extern int __encode_dotted(const char *dotted,
399-
unsigned char *dest,
400-
int maxlen) attribute_hidden;
401-
extern int __decode_dotted(const unsigned char *packet,
402-
int offset,
403-
int packet_len,
404-
char *dest,
405-
int dest_len) attribute_hidden;
406399
extern int __encode_header(struct resolv_header *h,
407400
unsigned char *dest,
408401
int maxlen) attribute_hidden;
@@ -416,6 +409,13 @@ extern int __encode_answer(struct resolv_answer *a,
416409
int maxlen) attribute_hidden;
417410
extern void __open_nameservers(void) attribute_hidden;
418411
extern void __close_nameservers(void) attribute_hidden;
412+
extern int __hnbad(const char *dotted) attribute_hidden;
413+
414+
#define __encode_dotted(dotted,dest,maxlen) \
415+
dn_comp((dotted), (dest), (maxlen), NULL, NULL)
416+
#define __decode_dotted(packet,offset,packet_len,dest,dest_len) \
417+
dn_expand((packet), (packet) + (packet_len), (packet) + (offset), \
418+
(dest), (dest_len))
419419

420420
/*
421421
* Theory of operation.
@@ -552,116 +552,6 @@ void __decode_header(unsigned char *data,
552552
#endif /* L_decodeh */
553553

554554

555-
#ifdef L_encoded
556-
557-
/* Encode a dotted string into nameserver transport-level encoding.
558-
This routine is fairly dumb, and doesn't attempt to compress
559-
the data */
560-
int __encode_dotted(const char *dotted, unsigned char *dest, int maxlen)
561-
{
562-
unsigned used = 0;
563-
564-
while (dotted && *dotted) {
565-
char *c = strchr(dotted, '.');
566-
int l = c ? c - dotted : strlen(dotted);
567-
568-
/* two consecutive dots are not valid */
569-
if (l == 0)
570-
return -1;
571-
572-
if (l >= (maxlen - used - 1))
573-
return -1;
574-
575-
dest[used++] = l;
576-
memcpy(dest + used, dotted, l);
577-
used += l;
578-
579-
if (!c)
580-
break;
581-
dotted = c + 1;
582-
}
583-
584-
if (maxlen < 1)
585-
return -1;
586-
587-
dest[used++] = 0;
588-
589-
return used;
590-
}
591-
#endif /* L_encoded */
592-
593-
594-
#ifdef L_decoded
595-
596-
/* Decode a dotted string from nameserver transport-level encoding.
597-
This routine understands compressed data. */
598-
int __decode_dotted(const unsigned char *packet,
599-
int offset,
600-
int packet_len,
601-
char *dest,
602-
int dest_len)
603-
{
604-
unsigned b;
605-
bool measure = 1;
606-
unsigned total = 0;
607-
unsigned used = 0;
608-
unsigned maxiter = 256;
609-
610-
if (!packet)
611-
return -1;
612-
613-
dest[0] = '\0';
614-
while (--maxiter) {
615-
if (offset >= packet_len)
616-
return -1;
617-
b = packet[offset++];
618-
if (b == 0)
619-
break;
620-
621-
if (measure)
622-
total++;
623-
624-
if ((b & 0xc0) == 0xc0) {
625-
if (offset >= packet_len)
626-
return -1;
627-
if (measure)
628-
total++;
629-
/* compressed item, redirect */
630-
offset = ((b & 0x3f) << 8) | packet[offset];
631-
measure = 0;
632-
continue;
633-
}
634-
635-
if (used + b + 1 >= dest_len)
636-
return -1;
637-
if (offset + b >= packet_len)
638-
return -1;
639-
memcpy(dest + used, packet + offset, b);
640-
offset += b;
641-
used += b;
642-
643-
if (measure)
644-
total += b;
645-
646-
if (packet[offset] != 0)
647-
dest[used++] = '.';
648-
else
649-
dest[used++] = '\0';
650-
}
651-
if (!maxiter)
652-
return -1;
653-
654-
/* The null byte must be counted too */
655-
if (measure)
656-
total++;
657-
658-
DPRINTF("Total decode len = %d\n", total);
659-
660-
return total;
661-
}
662-
#endif /* L_decoded */
663-
664-
665555
#ifdef L_encodeq
666556

667557
int __encode_question(const struct resolv_question *q,
@@ -1204,6 +1094,7 @@ int __dns_lookup(const char *name,
12041094
bool ends_with_dot;
12051095
bool contains_dot;
12061096
sockaddr46_t sa;
1097+
int num_answers;
12071098

12081099
fd = -1;
12091100
lookup = NULL;
@@ -1446,6 +1337,7 @@ int __dns_lookup(const char *name,
14461337
goto fail1;
14471338
}
14481339
pos = HFIXEDSZ;
1340+
/*XXX TODO: check that question matches query (and qdcount==1?) */
14491341
for (j = 0; j < h.qdcount; j++) {
14501342
DPRINTF("Skipping question %d at %d\n", j, pos);
14511343
i = __length_question(packet + pos, packet_len - pos);
@@ -1460,19 +1352,23 @@ int __dns_lookup(const char *name,
14601352
DPRINTF("Decoding answer at pos %d\n", pos);
14611353

14621354
first_answer = 1;
1355+
num_answers = 0;
14631356
a->dotted = NULL;
14641357
for (j = 0; j < h.ancount; j++) {
14651358
i = __decode_answer(packet, pos, packet_len, &ma);
14661359
if (i < 0) {
14671360
DPRINTF("failed decode %d\n", i);
14681361
/* If the message was truncated but we have
14691362
* decoded some answers, pretend it's OK */
1470-
if (j && h.tc)
1363+
if (num_answers && h.tc)
14711364
break;
14721365
goto try_next_server;
14731366
}
14741367
pos += i;
14751368

1369+
if (__hnbad(ma.dotted))
1370+
break;
1371+
++num_answers;
14761372
if (first_answer) {
14771373
ma.buf = a->buf;
14781374
ma.buflen = a->buflen;
@@ -1502,6 +1398,10 @@ int __dns_lookup(const char *name,
15021398
++a->add_count;
15031399
}
15041400
}
1401+
if (!num_answers) {
1402+
h_errno = NO_RECOVERY;
1403+
goto fail1;
1404+
}
15051405

15061406
/* Success! */
15071407
DPRINTF("Answer name = |%s|\n", a->dotted);
@@ -2468,7 +2368,7 @@ int gethostbyaddr_r(const void *addr, socklen_t addrlen,
24682368
/* Decode CNAME into buf, feed it to __dns_lookup() again */
24692369
i = __decode_dotted(packet, a.rdoffset, packet_len, buf, buflen);
24702370
free(packet);
2471-
if (i < 0) {
2371+
if (i < 0 || __hnbad(buf)) {
24722372
*h_errnop = NO_RECOVERY;
24732373
return -1;
24742374
}
@@ -2477,6 +2377,10 @@ int gethostbyaddr_r(const void *addr, socklen_t addrlen,
24772377
if (a.atype == T_PTR) { /* ADDRESS */
24782378
i = __decode_dotted(packet, a.rdoffset, packet_len, buf, buflen);
24792379
free(packet);
2380+
if (__hnbad(buf)) {
2381+
*h_errnop = NO_RECOVERY;
2382+
return -1;
2383+
}
24802384
result_buf->h_name = buf;
24812385
result_buf->h_addrtype = type;
24822386
result_buf->h_length = addrlen;
@@ -3041,6 +2945,51 @@ int ns_name_pton(const char *src, u_char *dst, size_t dstsiz)
30412945
}
30422946
libc_hidden_def(ns_name_pton)
30432947

2948+
/*
2949+
* __hnbad(dotted)
2950+
* Check whether a name is valid enough for DNS. The rules, as
2951+
* laid down by glibc, are:
2952+
* - printable input string
2953+
* - converts to label notation
2954+
* - each label only contains [0-9a-zA-Z_-], up to 63 octets
2955+
* - first label doesn’t begin with ‘-’
2956+
* This both is weaker than Unix hostnames (e.g. it allows
2957+
* underscores and leading/trailing hyphen-minus) and stronger
2958+
* than general (e.g. a leading “*.” is valid sometimes), take care.
2959+
* return:
2960+
* 0 if the name is ok
2961+
*/
2962+
int __hnbad(const char *dotted)
2963+
{
2964+
unsigned char c, n, *cp;
2965+
unsigned char buf[NS_MAXCDNAME];
2966+
2967+
cp = (unsigned char *)dotted;
2968+
while ((c = *cp++))
2969+
if (c < 0x21 || c > 0x7E)
2970+
return (1);
2971+
if (ns_name_pton(dotted, buf, sizeof(buf)) < 0)
2972+
return (2);
2973+
if (buf[0] > 0 && buf[1] == '-')
2974+
return (3);
2975+
cp = buf;
2976+
while ((n = *cp++)) {
2977+
if (n > 63)
2978+
return (4);
2979+
while (n--) {
2980+
c = *cp++;
2981+
if (c < '-' ||
2982+
(c > '-' && c < '0') ||
2983+
(c > '9' && c < 'A') ||
2984+
(c > 'Z' && c < '_') ||
2985+
(c > '_' && c < 'a') ||
2986+
c > 'z')
2987+
return (5);
2988+
}
2989+
}
2990+
return (0);
2991+
}
2992+
30442993
/*
30452994
* ns_name_unpack(msg, eom, src, dst, dstsiz)
30462995
* Unpack a domain name from a message, source may be compressed.

0 commit comments

Comments
 (0)