Guard routing against a null-deref. Bug 1639
[users/heiko/exim.git] / test / src / fakens.c
index d82dd7cbb7a2a51265710f1854e30a8c4cceeef6..aff5f40f6fbb1eadf7e62e99fdb4271c5dbd5a59 100644 (file)
@@ -51,11 +51,17 @@ and the domain is not found. It converts the the result to PASS_ON instead of
 HOST_NOT_FOUND.
 
 Any DNS record line in a zone file can be prefixed with "DELAY=" and
 HOST_NOT_FOUND.
 
 Any DNS record line in a zone file can be prefixed with "DELAY=" and
-a number of milliseconds (followed by whitespace).
+a number of milliseconds (followed by one space).
 
 
-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. */
+Any DNS record line in a zone file can be prefixed with "DNSSEC ";
+if all the records found by a lookup are marked
+as such then the response will have the "AD" bit set. 
+
+Any DNS record line in a zone file can be prefixed with "AA "
+if all the records found by a lookup are marked
+as such then the response will have the "AA" bit set.
+
+*/
 
 #include <ctype.h>
 #include <stdarg.h>
 
 #include <ctype.h>
 #include <stdarg.h>
@@ -292,6 +298,8 @@ 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
   qtypelen    the length of qtype
   pkptr       points to the output buffer pointer; this is updated
   countptr    points to the record count; this is updated
+  dnssec      points to the AD flag indicator; this updated
+  aa         points to the AA flag indicator; this updated
 
 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
 
 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
@@ -299,7 +307,7 @@ 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,
 
 static int
 find_records(FILE *f, uschar *zone, uschar *domain, uschar *qtype,
-  int qtypelen, uschar **pkptr, int *countptr, BOOL * dnssec)
+  int qtypelen, uschar **pkptr, int *countptr, BOOL * dnssec, BOOL * aa)
 {
 int yield = HOST_NOT_FOUND;
 int domainlen = Ustrlen(domain);
 {
 int yield = HOST_NOT_FOUND;
 int domainlen = Ustrlen(domain);
@@ -324,6 +332,7 @@ 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 */ 
 (void)fseek(f, 0, SEEK_SET);     /* Start again at the beginning */
 
 *dnssec = TRUE;                        /* cancelled by first nonsecure rec found */ 
+*aa = TRUE;                    /* cancelled by first non-authoritive record */
 
 /* Scan for RRs */
 
 
 /* Scan for RRs */
 
@@ -336,6 +345,7 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL)
   int tvalue = typeptr->value;
   int qtlen = qtypelen;
   BOOL rr_sec = FALSE;
   int tvalue = typeptr->value;
   int qtlen = qtypelen;
   BOOL rr_sec = FALSE;
+  BOOL rr_aa = FALSE;
   int delay = 0;
 
   p = buffer;
   int delay = 0;
 
   p = buffer;
@@ -360,16 +370,21 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL)
       rr_sec = TRUE;
       p += 7;
       }
       rr_sec = TRUE;
       p += 7;
       }
+    else if (Ustrncmp(p, US"AA ", 3) == 0)     /* tagged as authoritive */
+      {
+      rr_aa = TRUE;
+      p += 3;
+      }
     else if (Ustrncmp(p, US"DELAY=", 6) == 0)  /* delay before response */
       {
       for (p += 6; *p >= '0' && *p <= '9'; p++) delay = delay*10 + *p - '0';
     else if (Ustrncmp(p, US"DELAY=", 6) == 0)  /* delay before response */
       {
       for (p += 6; *p >= '0' && *p <= '9'; p++) delay = delay*10 + *p - '0';
-      while (isspace(*p)) p++;
+      if (isspace(*p)) p++;
       }
     else
       break;
     }
 
       }
     else
       break;
     }
 
-  if (!isspace(*p))
+  if (!isspace(*p))     /* new domain name */
     {
     uschar *pp = rrdomain;
     uschar *PP = RRdomain;
     {
     uschar *pp = rrdomain;
     uschar *PP = RRdomain;
@@ -388,7 +403,7 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL)
       pp[-1] = 0;
       PP[-1] = 0;
       }
       pp[-1] = 0;
       PP[-1] = 0;
       }
-    }
+    }                   /* else use previous line's domain name */
 
   /* Compare domain names; first check for a wildcard */
 
 
   /* Compare domain names; first check for a wildcard */
 
@@ -427,6 +442,9 @@ while (fgets(CS buffer, sizeof(buffer), f) != NULL)
   if (!rr_sec)
     *dnssec = FALSE;                   /* cancel AD return */
 
   if (!rr_sec)
     *dnssec = FALSE;                   /* cancel AD return */
 
+  if (!rr_aa)
+    *aa = FALSE;                       /* cancel AA return */
+
   yield = 0;
   *countptr = *countptr + 1;
 
   yield = 0;
   *countptr = *countptr + 1;
 
@@ -565,6 +583,55 @@ alarmfn(int sig)
 {
 }
 
 {
 }
 
+
+/*************************************************
+*     Special-purpose domains                    *
+*************************************************/
+
+static int
+special_manyhome(uschar * packet, uschar * domain)
+{
+uschar *pk = packet + 12;
+uschar *rdlptr;
+int i, j;
+
+memset(packet, 0, 12);
+
+for (i = 104; i <= 111; i++) for (j = 0; j <= 255; j++)
+  {
+  pk = packname(domain, pk);
+  *pk++ = (ns_t_a >> 8) & 255;
+  *pk++ = (ns_t_a) & 255;
+  *pk++ = 0;
+  *pk++ = 1;     /* class = IN */
+  pk += 4;       /* TTL field; don't care */
+  rdlptr = pk;   /* remember rdlength field */
+  pk += 2;
+
+  *pk++ = 10; *pk++ = 250; *pk++ = i; *pk++ = j;
+
+  rdlptr[0] = ((pk - rdlptr - 2) >> 8) & 255;
+  rdlptr[1] = (pk - rdlptr - 2) & 255;
+  }
+
+packet[6] = (2048 >> 8) & 255;
+packet[7] = 2048 & 255;
+packet[10] = 0;
+packet[11] = 0;
+
+(void)fwrite(packet, 1, pk - packet, stdout);
+return 0;
+}
+
+static int
+special_again(uschar * packet, uschar * domain)
+{
+int delay = atoi(CCS domain);  /* digits at the start of the name */
+if (delay > 0) sleep(delay);
+return TRY_AGAIN;
+}
+
+
 /*************************************************
 *           Entry point and main program         *
 *************************************************/
 /*************************************************
 *           Entry point and main program         *
 *************************************************/
@@ -589,6 +656,7 @@ uschar qtype[12];
 uschar packet[2048 * 32 + 32];
 uschar *pk = packet;
 BOOL dnssec;
 uschar packet[2048 * 32 + 32];
 uschar *pk = packet;
 BOOL dnssec;
+BOOL aa;
 
 signal(SIGALRM, alarmfn);
 
 
 signal(SIGALRM, alarmfn);
 
@@ -647,38 +715,11 @@ domain[domlen] = 0;
 for (i = 0; i < domlen; i++) domain[i] = tolower(domain[i]);
 
 if (Ustrcmp(domain, "manyhome.test.ex") == 0 && Ustrcmp(qtype, "A") == 0)
 for (i = 0; i < domlen; i++) domain[i] = tolower(domain[i]);
 
 if (Ustrcmp(domain, "manyhome.test.ex") == 0 && Ustrcmp(qtype, "A") == 0)
-  {
-  uschar *pk = packet + 12;
-  uschar *rdlptr;
-  int i, j;
-
-  memset(packet, 0, 12);
-
-  for (i = 104; i <= 111; i++) for (j = 0; j <= 255; j++)
-    {
-    pk = packname(domain, pk);
-    *pk++ = (ns_t_a >> 8) & 255;
-    *pk++ = (ns_t_a) & 255;
-    *pk++ = 0;
-    *pk++ = 1;     /* class = IN */
-    pk += 4;       /* TTL field; don't care */
-    rdlptr = pk;   /* remember rdlength field */
-    pk += 2;
-
-    *pk++ = 10; *pk++ = 250; *pk++ = i; *pk++ = j;
-
-    rdlptr[0] = ((pk - rdlptr - 2) >> 8) & 255;
-    rdlptr[1] = (pk - rdlptr - 2) & 255;
-    }
-
-  packet[6] = (2048 >> 8) & 255;
-  packet[7] = 2048 & 255;
-  packet[10] = 0;
-  packet[11] = 0;
-
-  (void)fwrite(packet, 1, pk - packet, stdout);
-  return 0;
-  }
+  return special_manyhome(packet, domain);
+else if (domlen >= 14 && Ustrcmp(domain + domlen - 14, "test.again.dns") == 0)
+  return special_again(packet, domain);
+else if (domlen >= 13 && Ustrcmp(domain + domlen - 13, "test.fail.dns") == 0)
+  return NO_RECOVERY;
 
 
 if (Ustrchr(domain, '.') == NULL && qualify != NULL &&
 
 
 if (Ustrchr(domain, '.') == NULL && qualify != NULL &&
@@ -728,7 +769,7 @@ if (f == NULL)
 /* Find the records we want, and add them to the result. */
 
 count = 0;
 /* Find the records we want, and add them to the result. */
 
 count = 0;
-yield = find_records(f, zone, domain, qtype, qtypelen, &pk, &count, &dnssec);
+yield = find_records(f, zone, domain, qtype, qtypelen, &pk, &count, &dnssec, &aa);
 if (yield == NO_RECOVERY) goto END_OFF;
 
 packet[6] = (count >> 8) & 255;
 if (yield == NO_RECOVERY) goto END_OFF;
 
 packet[6] = (count >> 8) & 255;
@@ -743,6 +784,9 @@ packet[11] = 0;
 if (dnssec)
   ((HEADER *)packet)->ad = 1;
 
 if (dnssec)
   ((HEADER *)packet)->ad = 1;
 
+if (aa)
+  ((HEADER *)packet)->aa = 1;
+
 /* Close the zone file, write the result, and return. */
 
 END_OFF:
 /* Close the zone file, write the result, and return. */
 
 END_OFF:
@@ -751,6 +795,6 @@ END_OFF:
 return yield;
 }
 
 return yield;
 }
 
-/* vi: aw ai sw=2
+/* vi: aw ai sw=2 sts=2 ts=8 et
 */
 /* End of fakens.c */
 */
 /* End of fakens.c */