]> source.dussan.org Git - rspamd.git/commitdiff
[Minor] Merge fake DNS records
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 26 Aug 2019 17:25:00 +0000 (18:25 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 26 Aug 2019 17:25:14 +0000 (18:25 +0100)
src/libserver/dns.c

index ab01bc8ed439b523effc047be024cf90d8160359..cf4279cf07c6fd6b66aa2300721abced10082de6 100644 (file)
@@ -326,208 +326,222 @@ rspamd_dns_resolv_conf_on_server (struct rdns_resolver *resolver,
 }
 
 static void
-rspamd_dns_resolver_config_ucl (struct rspamd_config *cfg,
-                                                               struct rspamd_dns_resolver *dns_resolver,
-                                                               const ucl_object_t *dns_section)
+rspamd_process_fake_reply (struct rspamd_config *cfg,
+               struct rspamd_dns_resolver *dns_resolver,
+               const ucl_object_t *cur_arr)
 {
-       const ucl_object_t *fake_replies, *cur;
+       const ucl_object_t *cur;
        ucl_object_iter_t it;
 
-       /* Process fake replies */
-       fake_replies = ucl_object_lookup_any (dns_section, "fake_records",
-                       "fake_replies", NULL);
+       it = ucl_object_iterate_new (cur_arr);
 
-       if (fake_replies && ucl_object_type (fake_replies) == UCL_ARRAY) {
-               it = ucl_object_iterate_new (fake_replies);
+       while ((cur = ucl_object_iterate_safe (it, true))) {
+               const ucl_object_t *type_obj, *name_obj, *code_obj, *replies_obj;
+               enum rdns_request_type rtype = RDNS_REQUEST_A;
+               enum dns_rcode rcode = RDNS_RC_NOERROR;
+               struct rdns_reply_entry *replies = NULL;
+               const gchar *name = NULL;
+
+               if (ucl_object_type (cur) != UCL_OBJECT) {
+                       continue;
+               }
+
+               name_obj = ucl_object_lookup (cur, "name");
+               if (name_obj == NULL ||
+                       (name = ucl_object_tostring (name_obj)) == NULL) {
+                       msg_err_config ("no name for fake dns reply");
+                       continue;
+               }
 
-               while ((cur = ucl_object_iterate_safe (it, true))) {
-                       const ucl_object_t *type_obj, *name_obj, *code_obj, *replies_obj;
-                       enum rdns_request_type rtype = RDNS_REQUEST_A;
-                       enum dns_rcode rcode = RDNS_RC_NOERROR;
-                       struct rdns_reply_entry *replies = NULL;
-                       const gchar *name = NULL;
+               type_obj = ucl_object_lookup (cur, "type");
+               if (type_obj) {
+                       rtype = rdns_type_fromstr (ucl_object_tostring (type_obj));
 
-                       if (ucl_object_type (cur) != UCL_OBJECT) {
+                       if (rtype == RDNS_REQUEST_INVALID) {
+                               msg_err_config ("invalid type for %s: %s", name,
+                                               ucl_object_tostring (type_obj));
                                continue;
                        }
+               }
 
-                       name_obj = ucl_object_lookup (cur, "name");
-                       if (name_obj == NULL ||
-                               (name = ucl_object_tostring (name_obj)) == NULL) {
-                               msg_err_config ("no name for fake dns reply");
+               code_obj = ucl_object_lookup_any (cur, "code", "rcode", NULL);
+               if (code_obj) {
+                       rcode = rdns_rcode_fromstr (ucl_object_tostring (code_obj));
+
+                       if (rcode == RDNS_RC_INVALID) {
+                               msg_err_config ("invalid rcode for %s: %s", name,
+                                               ucl_object_tostring (code_obj));
                                continue;
                        }
+               }
 
-                       type_obj = ucl_object_lookup (cur, "type");
-                       if (type_obj) {
-                               rtype = rdns_type_fromstr (ucl_object_tostring (type_obj));
+               if (rcode == RDNS_RC_NOERROR) {
+                       /* We want replies to be set for this rcode */
+                       replies_obj = ucl_object_lookup (cur, "replies");
 
-                               if (rtype == RDNS_REQUEST_INVALID) {
-                                       msg_err_config ("invalid type for %s: %s", name,
-                                                       ucl_object_tostring (type_obj));
-                                       continue;
-                               }
+                       if (replies_obj == NULL || ucl_object_type (replies_obj) != UCL_ARRAY) {
+                               msg_err_config ("invalid replies for fake DNS record %s", name);
+                               continue;
                        }
 
-                       code_obj = ucl_object_lookup_any (cur, "code", "rcode", NULL);
-                       if (code_obj) {
-                               rcode = rdns_rcode_fromstr (ucl_object_tostring (code_obj));
+                       ucl_object_iter_t rep_it;
+                       const ucl_object_t *rep_obj;
 
-                               if (rcode == RDNS_RC_INVALID) {
-                                       msg_err_config ("invalid rcode for %s: %s", name,
-                                                       ucl_object_tostring (code_obj));
-                                       continue;
-                               }
-                       }
+                       rep_it = ucl_object_iterate_new (replies_obj);
 
-                       if (rcode == RDNS_RC_NOERROR) {
-                               /* We want replies to be set for this rcode */
-                               replies_obj = ucl_object_lookup (cur, "replies");
+                       while ((rep_obj = ucl_object_iterate_safe (rep_it, true))) {
+                               const gchar *str_rep = ucl_object_tostring (rep_obj);
+                               struct rdns_reply_entry *rep;
+                               gchar **svec;
 
-                               if (replies_obj == NULL || ucl_object_type (replies_obj) != UCL_ARRAY) {
-                                       msg_err_config ("invalid replies for fake DNS record %s", name);
+                               if (str_rep == NULL) {
+                                       msg_err_config ("invalid reply element for fake DNS record %s",
+                                                       name);
                                        continue;
                                }
 
-                               ucl_object_iter_t rep_it;
-                               const ucl_object_t *rep_obj;
-
-                               rep_it = ucl_object_iterate_new (replies_obj);
+                               rep = calloc (1, sizeof (*rep));
+                               g_assert (rep != NULL);
 
-                               while ((rep_obj = ucl_object_iterate_safe (rep_it, true))) {
-                                       const gchar *str_rep = ucl_object_tostring (rep_obj);
-                                       struct rdns_reply_entry *rep;
-                                       gchar **svec;
+                               rep->type = rtype;
+                               rep->ttl = 0;
 
-                                       if (str_rep == NULL) {
-                                               msg_err_config ("invalid reply element for fake DNS record %s",
-                                                               name);
-                                               continue;
+                               switch (rtype) {
+                               case RDNS_REQUEST_A:
+                                       if (inet_pton (AF_INET, str_rep, &rep->content.a.addr) != 1) {
+                                               msg_err_config ("invalid A reply element for fake "
+                                                                               "DNS record %s: %s",
+                                                               name, str_rep);
+                                               free (rep);
                                        }
-
-                                       rep = calloc (1, sizeof (*rep));
-                                       g_assert (rep != NULL);
-
-                                       rep->type = rtype;
-                                       rep->ttl = 0;
-
-                                       switch (rtype) {
-                                       case RDNS_REQUEST_A:
-                                               if (inet_pton (AF_INET, str_rep, &rep->content.a.addr) != 1) {
-                                                       msg_err_config ("invalid A reply element for fake "
-                                                                                       "DNS record %s: %s",
-                                                                       name, str_rep);
-                                                       free (rep);
-                                               }
-                                               else {
-                                                       DL_APPEND (replies, rep);
-                                               }
-                                               break;
-                                       case RDNS_REQUEST_NS:
-                                               rep->content.ns.name = strdup (str_rep);
+                                       else {
                                                DL_APPEND (replies, rep);
-                                               break;
-                                       case RDNS_REQUEST_PTR:
-                                               rep->content.ptr.name = strdup (str_rep);
+                                       }
+                                       break;
+                               case RDNS_REQUEST_NS:
+                                       rep->content.ns.name = strdup (str_rep);
+                                       DL_APPEND (replies, rep);
+                                       break;
+                               case RDNS_REQUEST_PTR:
+                                       rep->content.ptr.name = strdup (str_rep);
+                                       DL_APPEND (replies, rep);
+                                       break;
+                               case RDNS_REQUEST_MX:
+                                       svec = g_strsplit_set (str_rep, " :", -1);
+
+                                       if (svec && svec[0] && svec[1]) {
+                                               rep->content.mx.priority = strtoul (svec[0], NULL, 10);
+                                               rep->content.mx.name = strdup (svec[1]);
                                                DL_APPEND (replies, rep);
-                                               break;
-                                       case RDNS_REQUEST_MX:
-                                               svec = g_strsplit_set (str_rep, " :", -1);
-
-                                               if (svec && svec[0] && svec[1]) {
-                                                       rep->content.mx.priority = strtoul (svec[0], NULL, 10);
-                                                       rep->content.mx.name = strdup (svec[1]);
-                                                       DL_APPEND (replies, rep);
-                                               }
-                                               else {
-                                                       msg_err_config ("invalid MX reply element for fake "
-                                                                                       "DNS record %s: %s",
-                                                                       name, str_rep);
-                                                       free (rep);
-                                               }
-
-                                               g_strfreev (svec);
-                                               break;
-                                       case RDNS_REQUEST_TXT:
-                                               rep->content.txt.data = strdup (str_rep);
+                                       }
+                                       else {
+                                               msg_err_config ("invalid MX reply element for fake "
+                                                                               "DNS record %s: %s",
+                                                               name, str_rep);
+                                               free (rep);
+                                       }
+
+                                       g_strfreev (svec);
+                                       break;
+                               case RDNS_REQUEST_TXT:
+                                       rep->content.txt.data = strdup (str_rep);
+                                       DL_APPEND (replies, rep);
+                                       break;
+                               case RDNS_REQUEST_SOA:
+                                       svec = g_strsplit_set (str_rep, " :", -1);
+
+                                       /* 7 elements */
+                                       if (svec && svec[0] && svec[1] && svec[2] &&
+                                               svec[3] && svec[4] && svec[5] && svec[6]) {
+                                               rep->content.soa.mname = strdup (svec[0]);
+                                               rep->content.soa.admin = strdup (svec[1]);
+                                               rep->content.soa.serial = strtoul (svec[2], NULL, 10);
+                                               rep->content.soa.refresh = strtol (svec[3], NULL, 10);
+                                               rep->content.soa.retry = strtol (svec[4], NULL, 10);
+                                               rep->content.soa.expire = strtol (svec[5], NULL, 10);
+                                               rep->content.soa.minimum = strtoul (svec[6], NULL, 10);
                                                DL_APPEND (replies, rep);
-                                               break;
-                                       case RDNS_REQUEST_SOA:
-                                               svec = g_strsplit_set (str_rep, " :", -1);
-
-                                               /* 7 elements */
-                                               if (svec && svec[0] && svec[1] && svec[2] &&
-                                                               svec[3] && svec[4] && svec[5] && svec[6]) {
-                                                       rep->content.soa.mname = strdup (svec[0]);
-                                                       rep->content.soa.admin = strdup (svec[1]);
-                                                       rep->content.soa.serial = strtoul (svec[2], NULL, 10);
-                                                       rep->content.soa.refresh = strtol (svec[3], NULL, 10);
-                                                       rep->content.soa.retry = strtol (svec[4], NULL, 10);
-                                                       rep->content.soa.expire = strtol (svec[5], NULL, 10);
-                                                       rep->content.soa.minimum = strtoul (svec[6], NULL, 10);
-                                                       DL_APPEND (replies, rep);
-                                               }
-                                               else {
-                                                       msg_err_config ("invalid MX reply element for fake "
-                                                                                       "DNS record %s: %s",
-                                                                       name, str_rep);
-                                                       free (rep);
-                                               }
-
-                                               g_strfreev (svec);
-                                               break;
-                                       case RDNS_REQUEST_AAAA:
-                                               if (inet_pton (AF_INET6, str_rep, &rep->content.aaa.addr) != 1) {
-                                                       msg_err_config ("invalid AAAA reply element for fake "
-                                                                                       "DNS record %s: %s",
-                                                                       name, str_rep);
-                                                       free (rep);
-                                               }
-                                               else {
-                                                       DL_APPEND (replies, rep);
-                                               }
-                                       case RDNS_REQUEST_SRV:
-                                       default:
-                                               msg_err_config ("invalid or unsupported reply element "
-                                                                               "for fake DNS record %s(%s): %s",
-                                                               name, rdns_str_from_type (rtype), str_rep);
+                                       }
+                                       else {
+                                               msg_err_config ("invalid MX reply element for fake "
+                                                                               "DNS record %s: %s",
+                                                               name, str_rep);
+                                               free (rep);
+                                       }
+
+                                       g_strfreev (svec);
+                                       break;
+                               case RDNS_REQUEST_AAAA:
+                                       if (inet_pton (AF_INET6, str_rep, &rep->content.aaa.addr) != 1) {
+                                               msg_err_config ("invalid AAAA reply element for fake "
+                                                                               "DNS record %s: %s",
+                                                               name, str_rep);
                                                free (rep);
-                                               break;
                                        }
+                                       else {
+                                               DL_APPEND (replies, rep);
+                                       }
+                               case RDNS_REQUEST_SRV:
+                               default:
+                                       msg_err_config ("invalid or unsupported reply element "
+                                                                       "for fake DNS record %s(%s): %s",
+                                                       name, rdns_str_from_type (rtype), str_rep);
+                                       free (rep);
+                                       break;
                                }
+                       }
 
-                               ucl_object_iterate_free (rep_it);
+                       ucl_object_iterate_free (rep_it);
 
-                               if (replies) {
-                                       struct rdns_reply_entry *tmp_entry;
-                                       guint i = 0;
-                                       DL_COUNT (replies, tmp_entry, i);
+                       if (replies) {
+                               struct rdns_reply_entry *tmp_entry;
+                               guint i = 0;
+                               DL_COUNT (replies, tmp_entry, i);
 
-                                       msg_info_config ("added fake record: %s(%s); %d replies", name,
-                                                       rdns_str_from_type (rtype), i);
-                                       rdns_resolver_set_fake_reply (dns_resolver->r,
-                                                       name, rtype, rcode, replies);
-                               }
-                               else {
-                                       msg_warn_config ("record %s has no replies, not adding",
-                                                       name);
-                               }
+                               msg_info_config ("added fake record: %s(%s); %d replies", name,
+                                               rdns_str_from_type (rtype), i);
+                               rdns_resolver_set_fake_reply (dns_resolver->r,
+                                               name, rtype, rcode, replies);
                        }
                        else {
-                               /* This entry returns some non valid code, no replies are possible */
-                               replies_obj = ucl_object_lookup (cur, "replies");
-
-                               if (replies_obj) {
-                                       msg_warn_config ("replies are set for non-successful return "
-                                         "code for %s(%s), they will be ignored", name, rdns_str_from_type (rtype));
-                               }
+                               msg_warn_config ("record %s has no replies, not adding",
+                                               name);
+                       }
+               }
+               else {
+                       /* This entry returns some non valid code, no replies are possible */
+                       replies_obj = ucl_object_lookup (cur, "replies");
 
-                               rdns_resolver_set_fake_reply (dns_resolver->r,
-                                               name, rtype, rcode, NULL);
+                       if (replies_obj) {
+                               msg_warn_config ("replies are set for non-successful return "
+                                                                "code for %s(%s), they will be ignored", name, rdns_str_from_type (rtype));
                        }
+
+                       rdns_resolver_set_fake_reply (dns_resolver->r,
+                                       name, rtype, rcode, NULL);
                }
+       }
 
-               ucl_object_iterate_free (it);
+       ucl_object_iterate_free (it);
+}
+
+static void
+rspamd_dns_resolver_config_ucl (struct rspamd_config *cfg,
+                                                               struct rspamd_dns_resolver *dns_resolver,
+                                                               const ucl_object_t *dns_section)
+{
+       const ucl_object_t *fake_replies;
+
+       /* Process fake replies */
+       fake_replies = ucl_object_lookup_any (dns_section, "fake_records",
+                       "fake_replies", NULL);
+
+       if (fake_replies && ucl_object_type (fake_replies) == UCL_ARRAY) {
+               const ucl_object_t *cur_arr;
+
+               DL_FOREACH (fake_replies, cur_arr) {
+                       rspamd_process_fake_reply (cfg, dns_resolver, cur_arr);
+               }
        }
 }
 
@@ -604,15 +618,19 @@ rspamd_dns_resolver_init (rspamd_logger_t *logger,
 
                if (cfg->rcl_obj) {
                        /* Configure additional options */
-                       const ucl_object_t *opts_section, *dns_section;
+                       const ucl_object_t *opts_section, *dns_section, *tmp;
 
                        opts_section = ucl_object_lookup (cfg->rcl_obj, "options");
 
                        if (opts_section) {
-                               dns_section = ucl_object_lookup (opts_section, "dns");
+                               /* TODO: implement a more simple merge logic */
+                               DL_FOREACH (opts_section, tmp) {
+                                       dns_section = ucl_object_lookup (opts_section, "dns");
 
-                               if (dns_section) {
-                                       rspamd_dns_resolver_config_ucl (cfg, dns_resolver, dns_section);
+                                       if (dns_section) {
+                                               rspamd_dns_resolver_config_ucl (cfg, dns_resolver,
+                                                               dns_section);
+                                       }
                                }
                        }
                }