ircd: move DNS resolution over to authd

This commit is contained in:
William Pitcock 2016-01-08 06:31:08 -06:00
parent c7c009b563
commit 1d02144f8b
9 changed files with 115 additions and 257 deletions

View file

@ -46,7 +46,7 @@ struct Blacklist {
struct BlacklistClient {
struct Blacklist *blacklist;
struct Client *client_p;
struct DNSQuery dns_query;
uint16_t dns_id;
rb_dlink_node node;
};

View file

@ -236,8 +236,6 @@ struct LocalUser
/* time challenge response is valid for */
time_t chal_time;
struct DNSQuery *dnsquery; /* for outgoing server's name lookup */
time_t next_away; /* Don't allow next away before... */
time_t last;
uint32_t connid;

View file

@ -41,7 +41,6 @@ struct Listener
int ssl; /* ssl listener */
int defer_accept; /* use TCP_DEFER_ACCEPT */
struct rb_sockaddr_storage addr;
struct DNSQuery *dns_query;
char vhost[HOSTLEN + 1]; /* virtual name of listener */
};

View file

@ -193,6 +193,8 @@ struct server_conf
char *class_name;
struct Class *class;
rb_dlink_node node;
uint16_t dns_query;
};
#define SERVER_ILLEGAL 0x0001

View file

@ -34,7 +34,7 @@
#include "stdinc.h"
#include "client.h"
#include "res.h"
#include "dns.h"
#include "numeric.h"
#include "reject.h"
#include "s_conf.h"
@ -60,27 +60,16 @@ static struct Blacklist *find_blacklist(char *name)
return NULL;
}
static inline int blacklist_check_reply(struct BlacklistClient *blcptr, struct rb_sockaddr_storage *addr)
static inline int blacklist_check_reply(struct BlacklistClient *blcptr, const char *ipaddr)
{
struct Blacklist *blptr = blcptr->blacklist;
char ipaddr[HOSTIPLEN];
char *lastoctet;
const char *lastoctet;
rb_dlink_node *ptr;
/* XXX the below two checks might want to change at some point
* e.g. if IPv6 blacklists don't use 127.x.y.z or A records anymore
* --Elizabeth
*/
if (addr->ss_family != AF_INET ||
memcmp(&((struct sockaddr_in *)addr)->sin_addr, "\177", 1))
goto blwarn;
/* No filters and entry found - thus positive match */
if (!rb_dlink_list_length(&blptr->filters))
return 1;
rb_inet_ntop_sock((struct sockaddr *)addr, ipaddr, sizeof(ipaddr));
/* Below will prolly have to change too if the above changes */
if ((lastoctet = strrchr(ipaddr, '.')) == NULL || *(++lastoctet) == '\0')
goto blwarn;
@ -88,7 +77,7 @@ static inline int blacklist_check_reply(struct BlacklistClient *blcptr, struct r
RB_DLINK_FOREACH(ptr, blcptr->blacklist->filters.head)
{
struct BlacklistFilter *filter = ptr->data;
char *cmpstr;
const char *cmpstr;
if (filter->type == BLACKLIST_FILTER_ALL)
cmpstr = ipaddr;
@ -118,7 +107,7 @@ blwarn:
return 0;
}
static void blacklist_dns_callback(void *vptr, struct DNSReply *reply)
static void blacklist_dns_callback(const char *result, int status, int aftype, void *vptr)
{
struct BlacklistClient *blcptr = (struct BlacklistClient *) vptr;
int listed = 0;
@ -134,9 +123,9 @@ static void blacklist_dns_callback(void *vptr, struct DNSReply *reply)
return;
}
if (reply != NULL)
if (result != NULL && status)
{
if (blacklist_check_reply(blcptr, &reply->addr))
if (blacklist_check_reply(blcptr, result))
listed = TRUE;
}
@ -167,9 +156,6 @@ static void initiate_blacklist_dnsquery(struct Blacklist *blptr, struct Client *
blcptr->blacklist = blptr;
blcptr->client_p = client_p;
blcptr->dns_query.ptr = blcptr;
blcptr->dns_query.callback = blacklist_dns_callback;
if ((client_p->localClient->ip.ss_family == AF_INET) && blptr->ipv4)
{
ip = (uint8_t *)&((struct sockaddr_in *)&client_p->localClient->ip)->sin_addr.s_addr;
@ -219,7 +205,7 @@ static void initiate_blacklist_dnsquery(struct Blacklist *blptr, struct Client *
else
return;
gethost_byname_type(buf, &blcptr->dns_query, T_A);
blcptr->dns_id = lookup_hostname(buf, AF_INET, blacklist_dns_callback, blcptr);
rb_dlinkAdd(blcptr, &blcptr->node, &client_p->preClient->dnsbl_queries);
blptr->refcount++;
@ -297,7 +283,7 @@ void abort_blacklist_queries(struct Client *client_p)
blcptr = ptr->data;
rb_dlinkDelete(&blcptr->node, &client_p->preClient->dnsbl_queries);
unref_blacklist(blcptr->blacklist);
delete_resolver_queries(&blcptr->dns_query);
cancel_lookup(blcptr->dns_id);
rb_free(blcptr);
}
}

View file

@ -1300,11 +1300,6 @@ exit_unknown_client(struct Client *client_p, struct Client *source_p, struct Cli
{
delete_auth_queries(source_p);
abort_blacklist_queries(source_p);
if (source_p->localClient->dnsquery)
{
delete_resolver_queries(source_p->localClient->dnsquery);
rb_free(source_p->localClient->dnsquery);
}
rb_dlinkDelete(&source_p->localClient->tnode, &unknown_list);
if(!IsIOError(source_p))

View file

@ -43,7 +43,7 @@
#include "ircd.h"
#include "numeric.h"
#include "packet.h"
#include "res.h"
#include "dns.h"
#include "logger.h"
#include "s_stats.h"
#include "send.h"
@ -55,7 +55,7 @@ struct AuthRequest
{
rb_dlink_node node;
struct Client *client; /* pointer to client struct for request */
struct DNSQuery dns_query; /* DNS Query */
uint16_t dns_id; /* DNS Query */
unsigned int flags; /* current state of request */
rb_fde_t *F; /* file descriptor for auth queries */
time_t timeout; /* time when query expires */
@ -198,7 +198,7 @@ release_auth_client(struct AuthRequest *auth)
* of success of failure
*/
static void
auth_dns_callback(void *vptr, struct DNSReply *reply)
auth_dns_callback(const char *result, int status, int aftype, void *vptr)
{
struct AuthRequest *auth = (struct AuthRequest *) vptr;
ClearDNSPending(auth);
@ -216,50 +216,16 @@ auth_dns_callback(void *vptr, struct DNSReply *reply)
return;
}
if(reply)
if(result != NULL && status)
{
int good = 1;
if(auth->client->localClient->ip.ss_family == AF_INET)
if(good && strlen(result) <= HOSTLEN)
{
struct sockaddr_in *ip, *ip_fwd;
ip = (struct sockaddr_in *) &auth->client->localClient->ip;
ip_fwd = (struct sockaddr_in *) &reply->addr;
if(ip->sin_addr.s_addr != ip_fwd->sin_addr.s_addr)
{
sendheader(auth->client, REPORT_HOST_MISMATCH);
good = 0;
}
}
#ifdef RB_IPV6
else if(auth->client->localClient->ip.ss_family == AF_INET6)
{
struct sockaddr_in6 *ip, *ip_fwd;
ip = (struct sockaddr_in6 *) &auth->client->localClient->ip;
ip_fwd = (struct sockaddr_in6 *) &reply->addr;
if(memcmp(&ip->sin6_addr, &ip_fwd->sin6_addr, sizeof(struct in6_addr)) != 0)
{
sendheader(auth->client, REPORT_HOST_MISMATCH);
good = 0;
}
}
#endif
else /* can't verify it, don't know how. reject it. */
{
sendheader(auth->client, REPORT_HOST_UNKNOWN);
good = 0;
}
if(good && strlen(reply->h_name) <= HOSTLEN)
{
rb_strlcpy(auth->client->host, reply->h_name, sizeof(auth->client->host));
rb_strlcpy(auth->client->host, result, sizeof(auth->client->host));
sendheader(auth->client, REPORT_FIN_DNS);
}
else if (strlen(reply->h_name) > HOSTLEN)
else if (strlen(result) > HOSTLEN)
sendheader(auth->client, REPORT_HOST_TOOLONG);
}
else
@ -447,13 +413,10 @@ start_auth(struct Client *client)
auth = make_auth_request(client);
auth->dns_query.ptr = auth;
auth->dns_query.callback = auth_dns_callback;
sendheader(client, REPORT_DO_DNS);
/* No DNS cache now, remember? -- adrian */
gethost_byaddr(&client->localClient->ip, &auth->dns_query);
auth->dns_id = lookup_ip(client->sockhost, GET_SS_FAMILY(&client->localClient->ip), auth_dns_callback, auth);
SetDNSPending(auth);
@ -493,7 +456,7 @@ timeout_auth_queries_event(void *notused)
if(IsDNSPending(auth))
{
ClearDNSPending(auth);
delete_resolver_queries(&auth->dns_query);
cancel_lookup(auth->dns_id);
sendheader(auth->client, REPORT_FAIL_DNS);
}
@ -636,7 +599,7 @@ delete_auth_queries(struct Client *target_p)
target_p->localClient->auth_request = NULL;
if(IsDNSPending(auth))
delete_resolver_queries(&auth->dns_query);
cancel_lookup(auth->dns_id);
if(auth->F != NULL)
rb_close(auth->F);

View file

@ -46,6 +46,7 @@
#include "irc_dictionary.h"
#include "s_assert.h"
#include "logger.h"
#include "dns.h"
rb_dlink_list shared_conf_list;
rb_dlink_list cluster_conf_list;
@ -354,6 +355,27 @@ free_server_conf(struct server_conf *server_p)
rb_free(server_p);
}
/*
* conf_dns_callback
* inputs - pointer to struct ConfItem
* - pointer to adns reply
* output - none
* side effects - called when resolver query finishes
* if the query resulted in a successful search, hp will contain
* a non-null pointer, otherwise hp will be null.
* if successful save hp in the conf item it was called with
*/
static void
conf_dns_callback(const char *result, int status, int aftype, void *data)
{
struct server_conf *server_p = data;
if(status == 1)
rb_inet_pton_sock(result, (struct sockaddr *)&server_p->my_ipnum);
server_p->dns_query = 0;
}
void
add_server_conf(struct server_conf *server_p)
{
@ -375,8 +397,11 @@ add_server_conf(struct server_conf *server_p)
server_p->class_name = rb_strdup("default");
}
if(strchr(server_p->host, '*') || strchr(server_p->host, '?'))
if(strpbrk(server_p->host, "*?"))
return;
server_p->dns_query =
lookup_hostname(server_p->host, GET_SS_FAMILY(&server_p->my_ipnum), conf_dns_callback, server_p);
}
struct server_conf *

View file

@ -971,139 +971,10 @@ server_estab(struct Client *client_p)
* -- adrian
*/
static int
serv_connect_resolved(struct Client *client_p)
{
struct rb_sockaddr_storage myipnum;
char vhoststr[HOSTIPLEN];
struct server_conf *server_p;
uint16_t port;
if((server_p = client_p->localClient->att_sconf) == NULL)
{
sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) ? L_NETWIDE : L_ALL, "Lost connect{} block for %s",
client_p->name);
exit_client(client_p, client_p, &me, "Lost connect{} block");
return 0;
}
#ifdef RB_IPV6
if(client_p->localClient->ip.ss_family == AF_INET6)
port = ntohs(((struct sockaddr_in6 *)&client_p->localClient->ip)->sin6_port);
else
#endif
port = ntohs(((struct sockaddr_in *)&client_p->localClient->ip)->sin_port);
if(ServerConfVhosted(server_p))
{
memcpy(&myipnum, &server_p->my_ipnum, sizeof(server_p->my_ipnum));
((struct sockaddr_in *)&myipnum)->sin_port = 0;
myipnum.ss_family = server_p->aftype;
}
else if(server_p->aftype == AF_INET && ServerInfo.specific_ipv4_vhost)
{
memcpy(&myipnum, &ServerInfo.ip, sizeof(ServerInfo.ip));
((struct sockaddr_in *)&myipnum)->sin_port = 0;
myipnum.ss_family = AF_INET;
SET_SS_LEN(&myipnum, sizeof(struct sockaddr_in));
}
#ifdef RB_IPV6
else if((server_p->aftype == AF_INET6) && ServerInfo.specific_ipv6_vhost)
{
memcpy(&myipnum, &ServerInfo.ip6, sizeof(ServerInfo.ip6));
((struct sockaddr_in6 *)&myipnum)->sin6_port = 0;
myipnum.ss_family = AF_INET6;
SET_SS_LEN(&myipnum, sizeof(struct sockaddr_in6));
}
#endif
else
{
/* log */
ilog(L_SERVER, "Connecting to %s[%s] port %d (%s)", client_p->name, client_p->sockhost, port,
#ifdef RB_IPV6
server_p->aftype == AF_INET6 ? "IPv6" :
#endif
(server_p->aftype == AF_INET ? "IPv4" : "?"));
if(ServerConfSSL(server_p))
{
rb_connect_tcp(client_p->localClient->F, (struct sockaddr *)&client_p->localClient->ip,
NULL, 0, serv_connect_ssl_callback,
client_p, ConfigFileEntry.connect_timeout);
}
else
rb_connect_tcp(client_p->localClient->F, (struct sockaddr *)&client_p->localClient->ip,
NULL, 0, serv_connect_callback,
client_p, ConfigFileEntry.connect_timeout);
return 1;
}
/* log */
rb_inet_ntop_sock((struct sockaddr *)&myipnum, vhoststr, sizeof vhoststr);
ilog(L_SERVER, "Connecting to %s[%s] port %d (%s) (vhost %s)", client_p->name, client_p->sockhost, port,
#ifdef RB_IPV6
server_p->aftype == AF_INET6 ? "IPv6" :
#endif
(server_p->aftype == AF_INET ? "IPv4" : "?"), vhoststr);
if(ServerConfSSL(server_p))
rb_connect_tcp(client_p->localClient->F, (struct sockaddr *)&client_p->localClient->ip,
(struct sockaddr *) &myipnum,
GET_SS_LEN(&myipnum), serv_connect_ssl_callback, client_p,
ConfigFileEntry.connect_timeout);
else
rb_connect_tcp(client_p->localClient->F, (struct sockaddr *)&client_p->localClient->ip,
(struct sockaddr *) &myipnum,
GET_SS_LEN(&myipnum), serv_connect_callback, client_p,
ConfigFileEntry.connect_timeout);
return 1;
}
static void
serv_connect_dns_callback(void *vptr, struct DNSReply *reply)
{
struct Client *client_p = vptr;
uint16_t port;
rb_free(client_p->localClient->dnsquery);
client_p->localClient->dnsquery = NULL;
if (reply == NULL)
{
sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) ? L_NETWIDE : L_ALL, "Cannot resolve hostname for %s",
client_p->name);
ilog(L_SERVER, "Cannot resolve hostname for %s",
log_client_name(client_p, HIDE_IP));
exit_client(client_p, client_p, &me, "Cannot resolve hostname");
return;
}
#ifdef RB_IPV6
if(reply->addr.ss_family == AF_INET6)
port = ((struct sockaddr_in6 *)&client_p->localClient->ip)->sin6_port;
else
#endif
port = ((struct sockaddr_in *)&client_p->localClient->ip)->sin_port;
memcpy(&client_p->localClient->ip, &reply->addr, sizeof(client_p->localClient->ip));
#ifdef RB_IPV6
if(reply->addr.ss_family == AF_INET6)
((struct sockaddr_in6 *)&client_p->localClient->ip)->sin6_port = port;
else
#endif
((struct sockaddr_in *)&client_p->localClient->ip)->sin_port = port;
/* Set sockhost properly now -- jilles */
rb_inet_ntop_sock((struct sockaddr *)&client_p->localClient->ip,
client_p->sockhost, sizeof client_p->sockhost);
serv_connect_resolved(client_p);
}
/*
* serv_connect() - initiate a server connection
*
* inputs - pointer to conf
* inputs - pointer to conf
* - pointer to client doing the connet
* output -
* side effects -
@ -1121,14 +992,18 @@ int
serv_connect(struct server_conf *server_p, struct Client *by)
{
struct Client *client_p;
struct rb_sockaddr_storage theiripnum;
rb_fde_t *F;
struct rb_sockaddr_storage myipnum;
char note[HOSTLEN + 10];
rb_fde_t *F;
s_assert(server_p != NULL);
if(server_p == NULL)
return 0;
/* log */
rb_inet_ntop_sock((struct sockaddr *)&server_p->my_ipnum, buf, sizeof(buf));
ilog(L_SERVER, "Connect to *[%s] @%s", server_p->name, buf);
/*
* Make sure this server isn't already connected
*/
@ -1144,27 +1019,32 @@ serv_connect(struct server_conf *server_p, struct Client *by)
}
/* create a socket for the server connection */
if((F = rb_socket(server_p->aftype, SOCK_STREAM, 0, NULL)) == NULL)
if((F = rb_socket(GET_SS_FAMILY(&server_p->my_ipnum), SOCK_STREAM, 0, NULL)) == NULL)
{
ilog_error("opening a stream socket");
return 0;
}
rb_snprintf(note, sizeof note, "Server: %s", server_p->name);
/* servernames are always guaranteed under HOSTLEN chars */
rb_snprintf(note, sizeof(note), "Server: %s", server_p->name);
rb_note(F, note);
/* Create a local client */
client_p = make_client(NULL);
/* Copy in the server, hostname, fd
* The sockhost may be a hostname, this will be corrected later
* -- jilles
*/
/* Copy in the server, hostname, fd */
rb_strlcpy(client_p->name, server_p->name, sizeof(client_p->name));
rb_strlcpy(client_p->host, server_p->host, sizeof(client_p->host));
rb_strlcpy(client_p->sockhost, server_p->host, sizeof(client_p->sockhost));
rb_strlcpy(client_p->sockhost, buf, sizeof(client_p->sockhost));
client_p->localClient->F = F;
add_to_cli_connid_hash(client_p);
/* shove the port number into the sockaddr */
#ifdef RB_IPV6
if(GET_SS_FAMILY(&server_p->my_ipnum) == AF_INET6)
((struct sockaddr_in6 *)&server_p->my_ipnum)->sin6_port = htons(server_p->port);
else
#endif
((struct sockaddr_in *)&server_p->my_ipnum)->sin_port = htons(server_p->port);
/*
* Set up the initial server evilness, ripped straight from
@ -1191,57 +1071,67 @@ serv_connect(struct server_conf *server_p, struct Client *by)
* The socket has been connected or connect is in progress.
*/
make_server(client_p);
if(by && IsPerson(by))
{
rb_strlcpy(client_p->serv->by, by->name,
sizeof client_p->serv->by);
if(client_p->serv->user)
free_user(client_p->serv->user, NULL);
client_p->serv->user = by->user;
by->user->refcnt++;
}
if(by && IsClient(by))
strcpy(client_p->serv->by, by->name);
else
{
rb_strlcpy(client_p->serv->by, "AutoConn.",
sizeof client_p->serv->by);
if(client_p->serv->user)
free_user(client_p->serv->user, NULL);
client_p->serv->user = NULL;
}
strcpy(client_p->serv->by, "AutoConn.");
SetConnecting(client_p);
rb_dlinkAddTail(client_p, &client_p->node, &global_client_list);
if (rb_inet_pton_sock(server_p->host, (struct sockaddr *)&theiripnum) > 0)
if(ServerConfVhosted(server_p))
{
memcpy(&client_p->localClient->ip, &theiripnum, sizeof(client_p->localClient->ip));
#ifdef RB_IPV6
if(theiripnum.ss_family == AF_INET6)
((struct sockaddr_in6 *)&client_p->localClient->ip)->sin6_port = htons(server_p->port);
else
#endif
((struct sockaddr_in *)&client_p->localClient->ip)->sin_port = htons(server_p->port);
memcpy(&myipnum, &server_p->my_ipnum, sizeof(myipnum));
((struct sockaddr_in *)&myipnum)->sin_port = 0;
SET_SS_FAMILY(&myipnum, GET_SS_FAMILY(&server_p->my_ipnum));
return serv_connect_resolved(client_p);
}
else if(GET_SS_FAMILY(&server_p->my_ipnum) == AF_INET && ServerInfo.specific_ipv4_vhost)
{
memcpy(&myipnum, &ServerInfo.ip, sizeof(myipnum));
((struct sockaddr_in *)&myipnum)->sin_port = 0;
SET_SS_FAMILY(&myipnum, AF_INET);
SET_SS_LEN(&myipnum, sizeof(struct sockaddr_in));
}
#ifdef RB_IPV6
else if((GET_SS_FAMILY(&server_p->my_ipnum) == AF_INET6) && ServerInfo.specific_ipv6_vhost)
{
memcpy(&myipnum, &ServerInfo.ip6, sizeof(myipnum));
((struct sockaddr_in6 *)&myipnum)->sin6_port = 0;
SET_SS_FAMILY(&myipnum, AF_INET6);
SET_SS_LEN(&myipnum, sizeof(struct sockaddr_in6));
}
#endif
else
{
#ifdef RB_IPV6
if(theiripnum.ss_family == AF_INET6)
((struct sockaddr_in6 *)&client_p->localClient->ip)->sin6_port = htons(server_p->port);
if(ServerConfSSL(server_p))
{
rb_connect_tcp(client_p->localClient->F,
(struct sockaddr *)&server_p->my_ipnum, NULL, 0,
serv_connect_ssl_callback, client_p,
ConfigFileEntry.connect_timeout);
}
else
#endif
((struct sockaddr_in *)&client_p->localClient->ip)->sin_port = htons(server_p->port);
rb_connect_tcp(client_p->localClient->F,
(struct sockaddr *)&server_p->my_ipnum, NULL, 0,
serv_connect_callback, client_p,
ConfigFileEntry.connect_timeout);
client_p->localClient->dnsquery = rb_malloc(sizeof(struct DNSQuery));
client_p->localClient->dnsquery->ptr = client_p;
client_p->localClient->dnsquery->callback = serv_connect_dns_callback;
gethost_byname_type(server_p->host, client_p->localClient->dnsquery,
#ifdef RB_IPV6
server_p->aftype == AF_INET6 ? T_AAAA :
#endif
T_A);
return 1;
}
if(ServerConfSSL(server_p))
rb_connect_tcp(client_p->localClient->F, (struct sockaddr *)&server_p->my_ipnum,
(struct sockaddr *)&myipnum,
GET_SS_LEN(&myipnum), serv_connect_ssl_callback, client_p,
ConfigFileEntry.connect_timeout);
else
rb_connect_tcp(client_p->localClient->F, (struct sockaddr *)&server_p->my_ipnum,
(struct sockaddr *)&myipnum,
GET_SS_LEN(&myipnum), serv_connect_callback, client_p,
ConfigFileEntry.connect_timeout);
return 1;
}
static void