rwrap: Handle trailing dot in dns names.
authorAndreas Schneider <asn@samba.org>
Tue, 4 Nov 2014 14:20:11 +0000 (15:20 +0100)
committerAndreas Schneider <asn@samba.org>
Thu, 27 Nov 2014 14:58:53 +0000 (15:58 +0100)
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Guenther Deschner <gd@samba.org>
src/resolv_wrapper.c
tests/test_dns_fake.c

index 07ec85ca99db3a929df9ce2f6fed98f11349ebcf..3b94a36bfe468691e37ad237550fbc5446608036 100644 (file)
@@ -558,6 +558,8 @@ static int rwrap_res_fake_hosts(const char *hostfile,
        int rc = ENOENT;
        char *key = NULL;
        char *value = NULL;
+       char *query_name = NULL;
+       size_t qlen = strlen(query);
 
        RWRAP_LOG(RWRAP_LOG_TRACE,
                  "Searching in fake hosts file %s\n", hostfile);
@@ -570,6 +572,15 @@ static int rwrap_res_fake_hosts(const char *hostfile,
                return -1;
        }
 
+       if (qlen > 0 && query[qlen-1] == '.') {
+               qlen--;
+       }
+
+       query_name = strndup(query, qlen);
+       if (query_name == NULL) {
+               return -1;
+       }
+
        while (fgets(buf, sizeof(buf), fp) != NULL) {
                char *rec_type;
                char *q;
@@ -593,23 +604,23 @@ static int rwrap_res_fake_hosts(const char *hostfile,
                        continue;
                }
 
-               if (TYPE_MATCH(type, ns_t_a, rec_type, "A", key, query)) {
+               if (TYPE_MATCH(type, ns_t_a, rec_type, "A", key, query_name)) {
                        rc = rwrap_fake_a(key, value, answer, anslen);
                        break;
                } else if (TYPE_MATCH(type, ns_t_aaaa,
-                                     rec_type, "AAAA", key, query)) {
+                                     rec_type, "AAAA", key, query_name)) {
                        rc = rwrap_fake_aaaa(key, value, answer, anslen);
                        break;
                } else if (TYPE_MATCH(type, ns_t_srv,
-                                     rec_type, "SRV", key, query)) {
+                                     rec_type, "SRV", key, query_name)) {
                        rc = rwrap_fake_srv(key, value, answer, anslen);
                        break;
                } else if (TYPE_MATCH(type, ns_t_soa,
-                                     rec_type, "SOA", key, query)) {
+                                     rec_type, "SOA", key, query_name)) {
                        rc = rwrap_fake_soa(key, value, answer, anslen);
                        break;
                } else if (TYPE_MATCH(type, ns_t_cname,
-                                     rec_type, "CNAME", key, query)) {
+                                     rec_type, "CNAME", key, query_name)) {
                        rc = rwrap_fake_cname(key, value, answer, anslen);
                        break;
                }
@@ -618,19 +629,20 @@ static int rwrap_res_fake_hosts(const char *hostfile,
        switch (rc) {
        case 0:
                RWRAP_LOG(RWRAP_LOG_TRACE,
-                               "Successfully faked answer for [%s]\n", query);
+                               "Successfully faked answer for [%s]\n", query_name);
                break;
        case -1:
                RWRAP_LOG(RWRAP_LOG_ERROR,
-                               "Error faking answer for [%s]\n", query);
+                               "Error faking answer for [%s]\n", query_name);
                break;
        case ENOENT:
                RWRAP_LOG(RWRAP_LOG_TRACE,
-                               "Record for [%s] not found\n", query);
+                               "Record for [%s] not found\n", query_name);
                rc = rwrap_fake_empty_query(key, type, answer, anslen);
                break;
        }
 
+       free(query_name);
        fclose(fp);
        return rc;
 }
index b890060e902332502904635afbd7056a25f259b3..0098e9a25392b3280d97583fcfa5e9f197eff795 100644 (file)
@@ -118,6 +118,40 @@ static void test_res_fake_a_query_case_insensitive(void **state)
        res_nclose(&dnsstate);
 }
 
+static void test_res_fake_a_query_trailing_dot(void **state)
+{
+       int rv;
+       struct __res_state dnsstate;
+       unsigned char answer[ANSIZE];
+       char addr[INET_ADDRSTRLEN];
+       ns_msg handle;
+       ns_rr rr;   /* expanded resource record */
+
+       (void) state; /* unused */
+
+       memset(&dnsstate, 0, sizeof(struct __res_state));
+       rv = res_ninit(&dnsstate);
+       assert_int_equal(rv, 0);
+
+       rv = res_nquery(&dnsstate, "cwrap.org.", ns_c_in, ns_t_a,
+                       answer, ANSIZE);
+       assert_int_not_equal(rv, -1);
+
+       ns_initparse(answer, 256, &handle);
+       /* The query must finish w/o an error, have one answer and the answer
+        * must be a parseable RR of type A and have the address that our
+        * fake hosts file contains
+        */
+       assert_int_equal(ns_msg_getflag(handle, ns_f_rcode), ns_r_noerror);
+       assert_int_equal(ns_msg_count(handle, ns_s_an), 1);
+       assert_int_equal(ns_parserr(&handle, ns_s_an, 0, &rr), 0);
+       assert_int_equal(ns_rr_type(rr), ns_t_a);
+       assert_non_null(inet_ntop(AF_INET, ns_rr_rdata(rr), addr, 256));
+       assert_string_equal(addr, "127.0.0.21");
+
+       res_nclose(&dnsstate);
+}
+
 static void test_res_fake_a_query_notfound(void **state)
 {
        int rv;
@@ -427,6 +461,7 @@ int main(void)
        const UnitTest tests[] = {
                unit_test(test_res_fake_a_query),
                unit_test(test_res_fake_a_query_case_insensitive),
+               unit_test(test_res_fake_a_query_trailing_dot),
                unit_test(test_res_fake_a_query_notfound),
                unit_test(test_res_fake_aaaa_query),
                unit_test(test_res_fake_aaaa_query_notfound),