X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/c55a77db55ebf46a399f136eeb3a928b1e862772..2dfb468b976206b91ff0677da1374dc78e5503e2:/test/src/fakens.c diff --git a/test/src/fakens.c b/test/src/fakens.c index 9ab7b7e2d..fd3604a3c 100644 --- a/test/src/fakens.c +++ b/test/src/fakens.c @@ -1,5 +1,3 @@ -/* $Cambridge: exim/test/src/fakens.c,v 1.1 2006/02/06 16:24:05 ph10 Exp $ */ - /************************************************* * fakens - A Fake Nameserver Program * *************************************************/ @@ -50,7 +48,11 @@ line in the zone file contains exactly this: PASS ON NOT FOUND and the domain is not found. It converts the the result to PASS_ON instead of -HOST_NOT_FOUND. */ +HOST_NOT_FOUND. + +Any DNS record line in a zone file can be prefixed with "DNSSEC" and +at least one space; if all the records found by a lookup are marked +as such then the response will have the "AD" bit set. */ #include #include @@ -81,12 +83,6 @@ typedef unsigned char uschar; #define Ustrncmp(s,t,n) strncmp(CCS(s),CCS(t),n) #define Ustrncpy(s,t,n) strncpy(CS(s),CCS(t),n) - -typedef struct adomainstr { - struct adomainstr *next; - uschar name[1]; -} adomainstr; - typedef struct zoneitem { uschar *zone; uschar *zonefile; @@ -103,21 +99,25 @@ not defined, assume we are in this state. A really old system might not even know about AAAA and SRV at all. */ #ifndef ns_t_a -#define ns_t_a T_A -#define ns_t_ns T_NS -#define ns_t_cname T_CNAME -#define ns_t_soa T_SOA -#define ns_t_ptr T_PTR -#define ns_t_mx T_MX -#define ns_t_txt T_TXT -#define ns_t_aaaa T_AAAA -#define ns_t_srv T_SRV -#ifndef T_AAAA -#define T_AAAA 28 -#endif -#ifndef T_SRV -#define T_SRV 33 -#endif +# define ns_t_a T_A +# define ns_t_ns T_NS +# define ns_t_cname T_CNAME +# define ns_t_soa T_SOA +# define ns_t_ptr T_PTR +# define ns_t_mx T_MX +# define ns_t_txt T_TXT +# define ns_t_aaaa T_AAAA +# define ns_t_srv T_SRV +# define ns_t_tlsa T_TLSA +# ifndef T_AAAA +# define T_AAAA 28 +# endif +# ifndef T_SRV +# define T_SRV 33 +# endif +# ifndef T_TLSA +# define T_TLSA 52 +# endif #endif static tlist type_list[] = { @@ -130,6 +130,7 @@ static tlist type_list[] = { { US"TXT", ns_t_txt }, { US"AAAA", ns_t_aaaa }, { US"SRV", ns_t_srv }, + { US"TLSA", ns_t_tlsa }, { NULL, 0 } }; @@ -193,6 +194,33 @@ while (*name != 0) return pk; } +uschar * +bytefield(uschar ** pp, uschar * pk) +{ +unsigned value = 0; +uschar * p = *pp; + +while (isdigit(*p)) value = value*10 + *p++ - '0'; +while (isspace(*p)) p++; +*pp = p; +*pk++ = value & 255; +return pk; +} + +uschar * +shortfield(uschar ** pp, uschar * pk) +{ +unsigned value = 0; +uschar * p = *pp; + +while (isdigit(*p)) value = value*10 + *p++ - '0'; +while (isspace(*p)) p++; +*pp = p; +*pk++ = (value >> 8) & 255; +*pk++ = value & 255; +return pk; +} + /************************************************* @@ -210,7 +238,6 @@ Arguments: qtypelen the length of qtype pkptr points to the output buffer pointer; this is updated countptr points to the record count; this is updated - adomainptr points to where to hang additional domains Returns: 0 on success, else HOST_NOT_FOUND or NO_DATA or NO_RECOVERY or PASS_ON - the latter if a "PASS ON NOT FOUND" line is seen @@ -218,16 +245,16 @@ Returns: 0 on success, else HOST_NOT_FOUND or NO_DATA or NO_RECOVERY or static int find_records(FILE *f, uschar *zone, uschar *domain, uschar *qtype, - int qtypelen, uschar **pkptr, int *countptr, adomainstr **adomainptr) + int qtypelen, uschar **pkptr, int *countptr, BOOL * dnssec) { int yield = HOST_NOT_FOUND; -int zonelen = Ustrlen(zone); int domainlen = Ustrlen(domain); BOOL pass_on_not_found = FALSE; tlist *typeptr; uschar *pk = *pkptr; uschar buffer[256]; uschar rrdomain[256]; +uschar RRdomain[256]; /* Decode the required type */ @@ -242,6 +269,8 @@ if (typeptr->name == NULL) rrdomain[0] = 0; /* No previous domain */ (void)fseek(f, 0, SEEK_SET); /* Start again at the beginning */ +*dnssec = TRUE; /* cancelled by first nonsecure rec found */ + /* Scan for RRs */ while (fgets(CS buffer, sizeof(buffer), f) != NULL) @@ -252,12 +281,13 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) int i, plen, value; int tvalue = typeptr->value; int qtlen = qtypelen; + BOOL rr_sec = FALSE; p = buffer; while (isspace(*p)) p++; if (*p == 0 || *p == ';') continue; - if (Ustrncmp(p, "PASS ON NOT FOUND", 17) == 0) + if (Ustrncmp(p, US"PASS ON NOT FOUND", 17) == 0) { pass_on_not_found = TRUE; continue; @@ -268,11 +298,31 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) *ep = 0; p = buffer; + if (Ustrncmp(p, US"DNSSEC ", 7) == 0) /* tagged as secure */ + { + rr_sec = TRUE; + p += 7; + } + if (!isspace(*p)) { uschar *pp = rrdomain; - while (!isspace(*p)) *pp++ = tolower(*p++); - if (pp[-1] != '.') Ustrcpy(pp, zone); else pp[-1] = 0; + uschar *PP = RRdomain; + while (!isspace(*p)) + { + *pp++ = tolower(*p); + *PP++ = *p++; + } + if (pp[-1] != '.') + { + Ustrcpy(pp, zone); + Ustrcpy(PP, zone); + } + else + { + pp[-1] = 0; + PP[-1] = 0; + } } /* Compare domain names; first check for a wildcard */ @@ -306,13 +356,19 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) /* Found a relevant record */ + if (!rr_sec) + *dnssec = FALSE; /* cancel AD return */ + yield = 0; *countptr = *countptr + 1; p += qtlen; while (isspace(*p)) p++; - pk = packname(domain, pk); /* Not rrdomain because of wildcard */ + /* For a wildcard record, use the search name; otherwise use the record's + name in its original case because it might contain upper case letters. */ + + pk = packname((rrdomain[0] == '*')? domain : RRdomain, pk); *pk++ = (tvalue >> 8) & 255; *pk++ = (tvalue) & 255; *pk++ = 0; @@ -363,12 +419,11 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) break; case ns_t_mx: - value = 0; - while (isdigit(*p)) value = value*10 + *p++ - '0'; - while (isspace(*p)) p++; - *pk++ = (value >> 8) & 255; - *pk++ = value & 255; - goto PACKNAME; + pk = shortfield(&p, pk); + if (ep[-1] != '.') sprintf(ep, "%s.", zone); + pk = packname(p, pk); + plen = Ustrlen(p); + break; case ns_t_txt: pp = pk++; @@ -377,6 +432,23 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) *pp = pk - pp - 1; break; + case ns_t_tlsa: + pk = bytefield(&p, pk); /* usage */ + pk = bytefield(&p, pk); /* selector */ + pk = bytefield(&p, pk); /* match type */ + while (isxdigit(*p)) + { + value = toupper(*p) - (isdigit(*p) ? '0' : '7') << 4; + if (isxdigit(*++p)) + { + value |= toupper(*p) - (isdigit(*p) ? '0' : '7'); + p++; + } + *pk++ = value & 255; + } + + break; + case ns_t_srv: for (i = 0; i < 3; i++) { @@ -392,20 +464,9 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) case ns_t_cname: case ns_t_ns: case ns_t_ptr: - PACKNAME: if (ep[-1] != '.') sprintf(ep, "%s.", zone); pk = packname(p, pk); plen = Ustrlen(p); - if (adomainptr != NULL && plen > zonelen + 2 && - Ustrncmp(p + plen - zonelen - 1, zone, zonelen) == 0) - { - adomainstr *adomain = (adomainstr *)malloc(sizeof(adomainstr) + plen); - *adomainptr = adomain; - adomainptr = &(adomain->next); - adomain->next = NULL; - Ustrncpy(adomain->name, p, plen - 1); - adomain->name[plen-1] = 0; - } break; } @@ -413,18 +474,6 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL) rdlptr[0] = ((pk - rdlptr - 2) >> 8) & 255; rdlptr[1] = (pk -rdlptr - 2) & 255; - - /* If we have just yielded a CNAME, we must change the domain name to the - new domain, and re-start the scan from the beginning. */ - - if (found_cname) - { - domain = fcopystring("%s", p); - domainlen = Ustrlen(domain); - domain[domainlen - 1] = 0; /* Removed trailing dot */ - rrdomain[0] = 0; /* No previous domain */ - (void)fseek(f, 0, SEEK_SET); /* Start again at the beginning */ - } } *pkptr = pk; @@ -442,13 +491,11 @@ main(int argc, char **argv) { FILE *f; DIR *d; -int dirlen, domlen, qtypelen; +int domlen, qtypelen; int yield, count; int i; int zonecount = 0; -tlist *typeptr; struct dirent *de; -adomainstr *adomain = NULL; zoneitem zones[32]; uschar *qualify = NULL; uschar *p, *zone; @@ -458,6 +505,7 @@ uschar buffer[256]; uschar qtype[12]; uschar packet[512]; uschar *pk = packet; +BOOL dnssec; if (argc != 4) { @@ -559,23 +607,20 @@ if (f == NULL) /* Find the records we want, and add them to the result. */ count = 0; -yield = find_records(f, zone, domain, qtype, qtypelen, &pk, &count, &adomain); +yield = find_records(f, zone, domain, qtype, qtypelen, &pk, &count, &dnssec); if (yield == NO_RECOVERY) goto END_OFF; packet[6] = (count >> 8) & 255; packet[7] = count & 255; -/* Search for additional records and add them to the result. */ +/* There is no need to return any additional records because Exim no longer +(from release 4.61) makes any use of them. */ -count = 0; -for (; adomain != NULL; adomain = adomain->next) - { - (void)find_records(f, zone, adomain->name, US"AAAA", 4, &pk, &count, NULL); - (void)find_records(f, zone, adomain->name, US"A", 1, &pk, &count, NULL); - } +packet[10] = 0; +packet[11] = 0; -packet[10] = (count >> 8) & 255; -packet[11] = count & 255; +if (dnssec) + ((HEADER *)packet)->ad = 1; /* Close the zone file, write the result, and return. */ @@ -585,4 +630,6 @@ END_OFF: return yield; } +/* vi: aw ai sw=2 +*/ /* End of fakens.c */