]> jfr.im git - solanum.git/blobdiff - authd/dns.c
chmode: Get elevated access for op-only queries
[solanum.git] / authd / dns.c
index 198a4ad3256114384b216a67905ba373d06cbbad..909c42a94bfd5288d9ca6b469018b3cf8b3c65b6 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "authd.h"
 #include "dns.h"
+#include "notice.h"
 #include "res.h"
 
 static void handle_lookup_ip_reply(void *data, struct DNSReply *reply);
@@ -42,13 +43,11 @@ lookup_ip(const char *host, int aftype, DNSCB callback, void *data)
                query->type = QUERY_A;
                g_type = T_A;
        }
-#ifdef RB_IPV6
        else if(aftype == AF_INET6)
        {
                query->type = QUERY_AAAA;
                g_type = T_AAAA;
        }
-#endif
        else
        {
                rb_free(query);
@@ -74,7 +73,7 @@ lookup_hostname(const char *ip, DNSCB callback, void *data)
        struct dns_query *query = rb_malloc(sizeof(struct dns_query));
        int aftype;
 
-       if(!rb_inet_pton_sock(ip, (struct sockaddr *)&query->addr))
+       if(!rb_inet_pton_sock(ip, &query->addr))
        {
                rb_free(query);
                return NULL;
@@ -84,10 +83,8 @@ lookup_hostname(const char *ip, DNSCB callback, void *data)
 
        if(aftype == AF_INET)
                query->type = QUERY_PTR_A;
-#ifdef RB_IPV6
        else if(aftype == AF_INET6)
                query->type = QUERY_PTR_AAAA;
-#endif
        else
        {
                rb_free(query);
@@ -118,14 +115,14 @@ static void
 handle_lookup_ip_reply(void *data, struct DNSReply *reply)
 {
        struct dns_query *query = data;
-       char ip[64] = "*";
-       query_type type = QUERY_INVALID;
+       char ip[HOSTIPLEN] = "*";
 
-       if(!query)
+       if(query == NULL)
+       {
                /* Shouldn't happen */
-               exit(2);
-
-       type = query->type;
+               warn_opers(L_CRIT, "DNS: handle_lookup_ip_reply: query == NULL!");
+               exit(EX_DNS_ERROR);
+       }
 
        if(reply == NULL)
                goto end;
@@ -136,7 +133,6 @@ handle_lookup_ip_reply(void *data, struct DNSReply *reply)
                if(GET_SS_FAMILY(&reply->addr) == AF_INET)
                        rb_inet_ntop_sock((struct sockaddr *)&reply->addr, ip, sizeof(ip));
                break;
-#ifdef RB_IPV6
        case QUERY_AAAA:
                if(GET_SS_FAMILY(&reply->addr) == AF_INET6)
                {
@@ -148,14 +144,15 @@ handle_lookup_ip_reply(void *data, struct DNSReply *reply)
                        }
                }
                break;
-#endif
        default:
-               exit(3);
+               warn_opers(L_CRIT, "DNS: handle_lookup_ip_reply: unknown query type %d",
+                               query->type);
+               exit(EX_DNS_ERROR);
        }
 
 end:
        if(query->callback)
-               query->callback(ip, ip[0] != '*', type, query->data);
+               query->callback(ip, ip[0] != '*', query->type, query->data);
 
        rb_free(query);
 }
@@ -166,13 +163,13 @@ handle_lookup_hostname_reply(void *data, struct DNSReply *reply)
 {
        struct dns_query *query = data;
        char *hostname = NULL;
-       query_type type = QUERY_INVALID;
 
        if(query == NULL)
+       {
                /* Shouldn't happen */
-               exit(4);
-
-       type = query->type;
+               warn_opers(L_CRIT, "DNS: handle_lookup_hostname_reply: query == NULL!");
+               exit(EX_DNS_ERROR);
+       }
 
        if(reply == NULL)
                goto end;
@@ -186,7 +183,6 @@ handle_lookup_hostname_reply(void *data, struct DNSReply *reply)
                if(ip->sin_addr.s_addr == ip_fwd->sin_addr.s_addr)
                        hostname = reply->h_name;
        }
-#ifdef RB_IPV6
        else if(query->type == QUERY_PTR_AAAA)
        {
                struct sockaddr_in6 *ip, *ip_fwd;
@@ -196,10 +192,13 @@ handle_lookup_hostname_reply(void *data, struct DNSReply *reply)
                if(memcmp(&ip->sin6_addr, &ip_fwd->sin6_addr, sizeof(struct in6_addr)) == 0)
                        hostname = reply->h_name;
        }
-#endif
        else
+       {
                /* Shouldn't happen */
-               exit(5);
+               warn_opers(L_CRIT, "DNS: handle_lookup_hostname_reply: unknown query type %d",
+                               query->type);
+               exit(EX_DNS_ERROR);
+       }
 end:
        if(query->callback)
                query->callback(hostname, hostname != NULL, query->type, query->data);
@@ -213,7 +212,10 @@ submit_dns_answer(const char *reply, bool status, query_type type, void *data)
        char *id = data;
 
        if(!id || type == QUERY_INVALID)
-               exit(6);
+       {
+               warn_opers(L_CRIT, "DNS: submit_dns_answer gave us a bad query");
+               exit(EX_DNS_ERROR);
+       }
 
        if(reply == NULL || status == false)
        {
@@ -227,7 +229,7 @@ submit_dns_answer(const char *reply, bool status, query_type type, void *data)
 }
 
 void
-resolve_dns(int parc, char *parv[])
+handle_resolve_dns(int parc, char *parv[])
 {
        char *id = rb_strdup(parv[1]);
        char qtype = *parv[2];
@@ -236,60 +238,61 @@ resolve_dns(int parc, char *parv[])
 
        switch(qtype)
        {
-#ifdef RB_IPV6
        case '6':
                aftype = AF_INET6;
-#endif
        case '4':
                if(!lookup_ip(record, aftype, submit_dns_answer, id))
                        submit_dns_answer(NULL, false, qtype, NULL);
                break;
-#ifdef RB_IPV6
        case 'S':
-#endif
        case 'R':
                if(!lookup_hostname(record, submit_dns_answer, id))
                        submit_dns_answer(NULL, false, qtype, NULL);
                break;
        default:
-               exit(7);
+               warn_opers(L_CRIT, "DNS: handle_resolve_dns got an unknown query: %c", qtype);
+               exit(EX_DNS_ERROR);
        }
 }
 
 void
-enumerate_nameservers(const char *rid, const char letter)
+enumerate_nameservers(uint32_t rid, const char letter)
 {
        char buf[(HOSTIPLEN + 1) * IRCD_MAXNS];
-       char *c = buf;
-       int i;
+       size_t s = 0;
 
        if (!irc_nscount)
        {
                /* Shouldn't happen */
-               rb_helper_write(authd_helper, "X %s %c NONAMESERVERS", rid, letter);
-               return;
+               warn_opers(L_CRIT, "DNS: no name servers!");
+               stats_error(rid, letter, "NONAMESERVERS");
+               exit(EX_DNS_ERROR);
        }
 
-       for(i = 0; i < irc_nscount; i++)
+       for(int i = 0; i < irc_nscount; i++)
        {
                char addr[HOSTIPLEN];
+               size_t addrlen;
 
                rb_inet_ntop_sock((struct sockaddr *)&irc_nsaddr_list[i], addr, sizeof(addr));
 
                if (!addr[0])
                {
                        /* Shouldn't happen */
-                       rb_helper_write(authd_helper, "X %s %c INVALIDNAMESERVER", rid, letter);
-                       return;
+                       warn_opers(L_CRIT, "DNS: bad nameserver!");
+                       stats_error(rid, letter, "INVALIDNAMESERVER");
+                       exit(EX_DNS_ERROR);
                }
 
-               (void)snprintf(c, HOSTIPLEN + 1, "%s ", addr);
-               c += strlen(addr) + 1;
+               addrlen = strlen(addr) + 1;
+               (void)snprintf(&buf[s], sizeof(buf) - s, "%s ", addr);
+               s += addrlen;
        }
 
-       *(--c) = '\0';
+       if(s > 0)
+               buf[--s] = '\0';
 
-       rb_helper_write(authd_helper, "Y %s %c %s", rid, letter, buf);
+       stats_result(rid, letter, "%s", buf);
 }
 
 void