]>
Commit | Line | Data |
---|---|---|
2b0cc3d3 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" | |
db821ee9 | 25 | #include "notice.h" |
2b0cc3d3 EM |
26 | #include "res.h" |
27 | #include "dns.h" | |
28 | ||
29 | struct user_query | |
30 | { | |
2b0cc3d3 EM |
31 | struct dns_query *query; /* Pending DNS query */ |
32 | time_t timeout; /* When the request times out */ | |
33 | }; | |
34 | ||
35 | /* Goinked from old s_auth.c --Elizabeth */ | |
36 | static const char *messages[] = | |
37 | { | |
38 | "*** Looking up your hostname...", | |
39 | "*** Found your hostname", | |
40 | "*** Couldn't look up your hostname", | |
41 | "*** Your hostname is too long, ignoring hostname", | |
42 | }; | |
43 | ||
44 | typedef enum | |
45 | { | |
46 | REPORT_LOOKUP, | |
47 | REPORT_FOUND, | |
48 | REPORT_FAIL, | |
49 | REPORT_TOOLONG, | |
50 | } dns_message; | |
51 | ||
3e875f62 EM |
52 | static void client_fail(struct auth_client *auth, dns_message message); |
53 | static void client_success(struct auth_client *auth); | |
410fcc23 | 54 | static void dns_answer_callback(const char *res, bool status, query_type type, void *data); |
2b0cc3d3 EM |
55 | |
56 | static struct ev_entry *timeout_ev; | |
57 | static EVH timeout_dns_queries_event; | |
14505c84 | 58 | static int rdns_timeout = 15; |
2b0cc3d3 | 59 | |
2b0cc3d3 | 60 | static void |
410fcc23 | 61 | dns_answer_callback(const char *res, bool status, query_type type, void *data) |
2b0cc3d3 | 62 | { |
3e875f62 EM |
63 | struct auth_client *auth = data; |
64 | struct user_query *query = auth->data[PROVIDER_RDNS]; | |
2b0cc3d3 | 65 | |
3e875f62 EM |
66 | if(query == NULL || res == NULL || status == false) |
67 | client_fail(auth, REPORT_FAIL); | |
2b0cc3d3 | 68 | else if(strlen(res) > HOSTLEN) |
3e875f62 EM |
69 | client_fail(auth, REPORT_TOOLONG); |
70 | else | |
2b0cc3d3 | 71 | { |
3e875f62 EM |
72 | rb_strlcpy(auth->hostname, res, HOSTLEN + 1); |
73 | client_success(auth); | |
2b0cc3d3 EM |
74 | } |
75 | } | |
76 | ||
77 | /* Timeout outstanding queries */ | |
646e6567 EM |
78 | static void |
79 | timeout_dns_queries_event(void *notused) | |
2b0cc3d3 | 80 | { |
3e875f62 | 81 | struct auth_client *auth; |
aba29d5a | 82 | rb_dictionary_iter iter; |
2b0cc3d3 | 83 | |
ab33d608 | 84 | RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) |
2b0cc3d3 | 85 | { |
3e875f62 | 86 | struct user_query *query = auth->data[PROVIDER_RDNS]; |
2b0cc3d3 | 87 | |
3e875f62 | 88 | if(query != NULL && query->timeout < rb_current_time()) |
2b0cc3d3 | 89 | { |
3e875f62 | 90 | client_fail(auth, REPORT_FAIL); |
2b0cc3d3 EM |
91 | return; |
92 | } | |
93 | } | |
94 | } | |
95 | ||
646e6567 EM |
96 | static void |
97 | client_fail(struct auth_client *auth, dns_message report) | |
2b0cc3d3 | 98 | { |
3e875f62 EM |
99 | struct user_query *query = auth->data[PROVIDER_RDNS]; |
100 | ||
101 | if(query == NULL) | |
102 | return; | |
2b0cc3d3 EM |
103 | |
104 | rb_strlcpy(auth->hostname, "*", sizeof(auth->hostname)); | |
3e875f62 | 105 | |
db821ee9 | 106 | notice_client(auth->cid, messages[report]); |
2b0cc3d3 | 107 | cancel_query(query->query); |
3e875f62 EM |
108 | |
109 | rb_free(query); | |
110 | auth->data[PROVIDER_RDNS] = NULL; | |
111 | ||
2b0cc3d3 EM |
112 | provider_done(auth, PROVIDER_RDNS); |
113 | } | |
114 | ||
646e6567 EM |
115 | static void |
116 | client_success(struct auth_client *auth) | |
2b0cc3d3 | 117 | { |
3e875f62 | 118 | struct user_query *query = auth->data[PROVIDER_RDNS]; |
2b0cc3d3 | 119 | |
db821ee9 | 120 | notice_client(auth->cid, messages[REPORT_FOUND]); |
2b0cc3d3 | 121 | cancel_query(query->query); |
3e875f62 EM |
122 | |
123 | rb_free(query); | |
124 | auth->data[PROVIDER_RDNS] = NULL; | |
125 | ||
2b0cc3d3 EM |
126 | provider_done(auth, PROVIDER_RDNS); |
127 | } | |
128 | ||
646e6567 | 129 | static bool |
6ced6a1f | 130 | rdns_init(void) |
646e6567 EM |
131 | { |
132 | timeout_ev = rb_event_addish("timeout_dns_queries_event", timeout_dns_queries_event, NULL, 1); | |
133 | return (timeout_ev != NULL); | |
134 | } | |
135 | ||
136 | static void | |
6ced6a1f | 137 | rdns_destroy(void) |
646e6567 EM |
138 | { |
139 | struct auth_client *auth; | |
140 | rb_dictionary_iter iter; | |
141 | ||
142 | RB_DICTIONARY_FOREACH(auth, &iter, auth_clients) | |
143 | { | |
144 | if(auth->data[PROVIDER_RDNS] != NULL) | |
145 | client_fail(auth, REPORT_FAIL); | |
146 | } | |
147 | ||
148 | rb_event_delete(timeout_ev); | |
149 | } | |
150 | ||
151 | static bool | |
6ced6a1f | 152 | rdns_start(struct auth_client *auth) |
646e6567 EM |
153 | { |
154 | struct user_query *query = rb_malloc(sizeof(struct user_query)); | |
155 | ||
156 | query->timeout = rb_current_time() + rdns_timeout; | |
157 | ||
158 | auth->data[PROVIDER_RDNS] = query; | |
159 | ||
160 | query->query = lookup_hostname(auth->c_ip, dns_answer_callback, auth); | |
161 | ||
162 | notice_client(auth->cid, messages[REPORT_LOOKUP]); | |
163 | set_provider_on(auth, PROVIDER_RDNS); | |
164 | return true; | |
165 | } | |
166 | ||
167 | static void | |
6ced6a1f | 168 | rdns_cancel(struct auth_client *auth) |
646e6567 EM |
169 | { |
170 | struct user_query *query = auth->data[PROVIDER_RDNS]; | |
171 | ||
172 | if(query != NULL) | |
173 | client_fail(auth, REPORT_FAIL); | |
174 | } | |
175 | ||
176 | static void | |
177 | add_conf_dns_timeout(const char *key, int parc, const char **parv) | |
178 | { | |
179 | int timeout = atoi(parv[0]); | |
180 | ||
181 | if(timeout < 0) | |
182 | { | |
183 | warn_opers(L_CRIT, "BUG: DNS timeout < 0 (value: %d)", timeout); | |
184 | return; | |
185 | } | |
186 | ||
187 | rdns_timeout = timeout; | |
188 | } | |
189 | ||
190 | struct auth_opts_handler rdns_options[] = | |
191 | { | |
bd7c2037 | 192 | { "rdns_timeout", 1, add_conf_dns_timeout }, |
646e6567 EM |
193 | { NULL, 0, NULL }, |
194 | }; | |
195 | ||
2b0cc3d3 EM |
196 | struct auth_provider rdns_provider = |
197 | { | |
198 | .id = PROVIDER_RDNS, | |
6ced6a1f EM |
199 | .init = rdns_init, |
200 | .destroy = rdns_destroy, | |
201 | .start = rdns_start, | |
202 | .cancel = rdns_cancel, | |
2b0cc3d3 | 203 | .completed = NULL, |
646e6567 | 204 | .opt_handlers = rdns_options, |
2b0cc3d3 | 205 | }; |