]> jfr.im git - solanum.git/blame - authd/providers/rdns.c
authd: identd fixes
[solanum.git] / authd / providers / rdns.c
CommitLineData
18764319
EM
1/* authd/providers/rdns.c - rDNS lookup provider for authd
2 * Copyright (c) 2016 Elizabeth Myers <elizabeth@interlinked.me>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice is present in all copies.
7 *
8 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
9 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
11 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
12 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
13 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
14 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
15 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
16 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
17 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
18 * POSSIBILITY OF SUCH DAMAGE.
19 */
20
21#include "stdinc.h"
22#include "rb_commio.h"
23#include "authd.h"
24#include "provider.h"
25#include "res.h"
26#include "dns.h"
27
28struct dns_query
29{
30 rb_dlink_node node;
31
32 struct auth_client *auth; /* Our client */
33 struct DNSQuery query; /* DNS query */
34 time_t timeout; /* When the request times out */
35};
36
37/* Goinked from old s_auth.c --Elizabeth */
38static const char *messages[] =
39{
40 "*** Looking up your hostname...",
41 "*** Found your hostname",
42 "*** Couldn't look up your hostname",
43 "*** Your hostname is too long, ignoring hostname",
44};
45
46typedef enum
47{
48 REPORT_LOOKUP,
49 REPORT_FOUND,
50 REPORT_FAIL,
51 REPORT_TOOLONG,
52} dns_message;
53
54static EVH timeout_dns_queries_event;
55static void client_fail(struct dns_query *query, dns_message message);
56static void client_success(struct dns_query *query);
57static void get_dns_answer(void *userdata, struct DNSReply *reply);
58
f1861e48 59static rb_dlink_list queries;
18764319 60static struct ev_entry *timeout_ev;
f1861e48 61static int rdns_timeout = 30;
18764319
EM
62
63
64bool client_dns_init(void)
65{
f1861e48 66 timeout_ev = rb_event_addish("timeout_dns_queries_event", timeout_dns_queries_event, NULL, 5);
18764319
EM
67 return (timeout_ev != NULL);
68}
69
70void client_dns_destroy(void)
71{
72 rb_dlink_node *ptr, *nptr;
73 struct dns_query *query;
74
75 RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head)
76 {
77 client_fail(ptr->data, REPORT_FAIL);
78 rb_dlinkDelete(ptr, &queries);
79 rb_free(ptr);
80 }
81
82 rb_event_delete(timeout_ev);
83}
84
85bool client_dns_start(struct auth_client *auth)
86{
87 struct dns_query *query = rb_malloc(sizeof(struct dns_query));
88
89 query->auth = auth;
f1861e48 90 query->timeout = rb_current_time() + rdns_timeout;
18764319
EM
91
92 query->query.ptr = query;
93 query->query.callback = get_dns_answer;
94
95 gethost_byaddr(&auth->c_addr, &query->query);
96 notice_client(auth, messages[REPORT_LOOKUP]);
9eb410b3 97 set_provider(auth, PROVIDER_RDNS);
18764319
EM
98 return true;
99}
100
101void client_dns_cancel(struct auth_client *auth)
102{
103 rb_dlink_node *ptr;
104
105 /* Bah, the stupid DNS resolver code doesn't have a cancellation
106 * func... */
107 RB_DLINK_FOREACH(ptr, queries.head)
108 {
109 struct dns_query *query = ptr->data;
110
111 if(query->auth == auth)
112 {
113 /* This will get cleaned up later by the DNS stuff */
114 client_fail(query, REPORT_FAIL);
115 return;
116 }
117 }
118}
119
120static void
121get_dns_answer(void *userdata, struct DNSReply *reply)
122{
123 struct dns_query *query = userdata;
124 struct auth_client *auth = query->auth;
125 rb_dlink_node *ptr, *nptr;
126 bool fail = false;
127 dns_message response;
128
129 if(reply == NULL || auth == NULL)
130 {
131 response = REPORT_FAIL;
132 fail = true;
133 goto cleanup;
134 }
135
136 if(!sockcmp(&auth->c_addr, &reply->addr, GET_SS_FAMILY(&auth->c_addr)))
137 {
138 response = REPORT_FAIL;
139 fail = true;
140 goto cleanup;
141 }
142
143 if(strlen(reply->h_name) > HOSTLEN)
144 {
145 /* Ah well. */
146 response = REPORT_TOOLONG;
147 fail = true;
148 goto cleanup;
149 }
150
151 rb_strlcpy(auth->hostname, reply->h_name, HOSTLEN + 1);
152
153cleanup:
154 /* Clean us up off the pending queries list */
155 RB_DLINK_FOREACH_SAFE(ptr, nptr, queries.head)
156 {
157 struct dns_query *query_l = ptr->data;
158
159 if(query == query_l)
160 {
161 /* Found */
162 if(fail)
163 client_fail(query, response);
164 else
165 client_success(query);
166
167 rb_dlinkDelete(ptr, &queries);
168 rb_free(query);
169 return;
170 }
171 }
172}
173
174/* Timeout outstanding queries */
175static void timeout_dns_queries_event(void *notused)
176{
177 rb_dlink_node *ptr;
178
179 /* NOTE - we do not delete queries from the list from a timeout, when
180 * the query times out later it will be deleted.
181 */
182 RB_DLINK_FOREACH(ptr, queries.head)
183 {
184 struct dns_query *query = ptr->data;
185
186 if(query->auth && query->timeout < rb_current_time())
187 {
188 client_fail(query, REPORT_FAIL);
18764319
EM
189 }
190 }
191}
192
193static void client_fail(struct dns_query *query, dns_message report)
194{
195 struct auth_client *auth = query->auth;
196
197 if(auth)
198 {
199 rb_strlcpy(auth->hostname, "*", sizeof(auth->hostname));
200 notice_client(auth, messages[report]);
201 provider_done(auth, PROVIDER_RDNS);
202 query->auth = NULL;
203 }
204}
205
206static void client_success(struct dns_query *query)
207{
208 struct auth_client *auth = query->auth;
209
210 if(auth)
211 {
212 notice_client(auth, messages[REPORT_FOUND]);
213 provider_done(auth, PROVIDER_RDNS);
214 query->auth = NULL;
215 }
216}
217
218struct auth_provider rdns_provider =
219{
220 .id = PROVIDER_RDNS,
221 .init = client_dns_init,
222 .destroy = client_dns_destroy,
223 .start = client_dns_start,
224 .cancel = client_dns_cancel,
225 .completed = NULL,
226};