]> git.ipfire.org Git - thirdparty/dhcp.git/blame - omapip/isclib.c
[#182] Corrected CVE: CVE-2021-25217
[thirdparty/dhcp.git] / omapip / isclib.c
CommitLineData
98bf1607 1/*
49a7fb58 2 * Copyright(C) 2009-2022 Internet Systems Consortium, Inc.("ISC")
98bf1607 3 *
7512d88b
TM
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
98bf1607
SR
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
14 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 *
16 * Internet Systems Consortium, Inc.
429a56d7
TM
17 * PO Box 360
18 * Newmarket, NH 03857 USA
98bf1607
SR
19 * <info@isc.org>
20 * http://www.isc.org/
21 *
22 */
23
24/*Trying to figure out what we need to define to get things to work.
ae91e4db 25 It looks like we want/need the library but need the fdwatchcommand
98bf1607
SR
26 which may be a problem */
27
28#include "dhcpd.h"
29
3ac2a573 30#include <sys/time.h>
47e8308d 31#include <signal.h>
3ac2a573 32
98bf1607 33dhcp_context_t dhcp_gbl_ctx;
0895c955 34int shutdown_signal = 0;
98bf1607 35
e54ff84f
SR
36#if defined (NSUPDATE)
37
38/* This routine will open up the /etc/resolv.conf file and
39 * send any nameservers it finds to the DNS client code.
40 * It may be moved to be part of the dns client code instead
41 * of being in the DHCP code
42 */
f6b8f48d 43isc_result_t
e54ff84f
SR
44dhcp_dns_client_setservers(void)
45{
46 isc_result_t result;
47 irs_resconf_t *resconf = NULL;
48 isc_sockaddrlist_t *nameservers;
49 isc_sockaddr_t *sa;
50
51 result = irs_resconf_load(dhcp_gbl_ctx.mctx, _PATH_RESOLV_CONF,
52 &resconf);
22ceb8bb 53 if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) {
e54ff84f
SR
54 log_error("irs_resconf_load failed: %d.", result);
55 return (result);
56 }
57
58 nameservers = irs_resconf_getnameservers(resconf);
59
60 /* Initialize port numbers */
61 for (sa = ISC_LIST_HEAD(*nameservers);
62 sa != NULL;
63 sa = ISC_LIST_NEXT(sa, link)) {
64 switch (sa->type.sa.sa_family) {
65 case AF_INET:
66 sa->type.sin.sin_port = htons(NS_DEFAULTPORT);
67 break;
68 case AF_INET6:
69 sa->type.sin6.sin6_port = htons(NS_DEFAULTPORT);
70 break;
71 default:
72 break;
73 }
74 }
75
76 result = dns_client_setservers(dhcp_gbl_ctx.dnsclient,
77 dns_rdataclass_in,
78 NULL, nameservers);
79 if (result != ISC_R_SUCCESS) {
80 log_error("dns_client_setservers failed: %d.",
81 result);
82 }
83 return (result);
84}
650ae59e 85#endif /* defined NSUPDATE */
e54ff84f 86
98bf1607
SR
87void
88isclib_cleanup(void)
89{
90#if defined (NSUPDATE)
91 if (dhcp_gbl_ctx.dnsclient != NULL)
92 dns_client_destroy((dns_client_t **)&dhcp_gbl_ctx.dnsclient);
650ae59e 93#endif /* defined NSUPDATE */
98bf1607
SR
94
95 if (dhcp_gbl_ctx.task != NULL) {
98bf1607
SR
96 isc_task_shutdown(dhcp_gbl_ctx.task);
97 isc_task_detach(&dhcp_gbl_ctx.task);
98 }
99
100 if (dhcp_gbl_ctx.timermgr != NULL)
101 isc_timermgr_destroy(&dhcp_gbl_ctx.timermgr);
102
103 if (dhcp_gbl_ctx.socketmgr != NULL)
104 isc_socketmgr_destroy(&dhcp_gbl_ctx.socketmgr);
105
106 if (dhcp_gbl_ctx.taskmgr != NULL)
107 isc_taskmgr_destroy(&dhcp_gbl_ctx.taskmgr);
108
109 if (dhcp_gbl_ctx.actx_started != ISC_FALSE) {
110 isc_app_ctxfinish(dhcp_gbl_ctx.actx);
111 dhcp_gbl_ctx.actx_started = ISC_FALSE;
112 }
113
114 if (dhcp_gbl_ctx.actx != NULL)
115 isc_appctx_destroy(&dhcp_gbl_ctx.actx);
116
117 if (dhcp_gbl_ctx.mctx != NULL)
118 isc_mem_detach(&dhcp_gbl_ctx.mctx);
119
120 return;
121}
122
6067cd48
TM
123/* Installs a handler for a signal using sigaction */
124static void
125handle_signal(int sig, void (*handler)(int)) {
126 struct sigaction sa;
127
128 memset(&sa, 0, sizeof(sa));
129 sa.sa_handler = handler;
130 sigfillset(&sa.sa_mask);
131 if (sigaction(sig, &sa, NULL) != 0) {
132 log_debug("handle_signal() failed for signal %d error: %s",
133 sig, strerror(errno));
134 }
135}
136
0cd94b5e
TM
137/* Callback passed to isc_app_ctxonrun
138 *
139 * BIND9 context code will invoke this handler once the context has
140 * entered the running state. We use it to set a global marker so that
141 * we can tell if the context is running. Several of the isc_app_
142 * calls REQUIRE that the context is running and we need a way to
143 * know that.
144 *
145 * We also check to see if we received a shutdown signal prior to
146 * the context entering the run state. If we did, then we can just
147 * simply shut the context down now. This closes the relatively
148 * small window between start up and entering run via the call
149 * to dispatch().
150 *
151 */
152static void
153set_ctx_running(isc_task_t *task, isc_event_t *event) {
154 IGNORE_UNUSED(task);
155 dhcp_gbl_ctx.actx_running = ISC_TRUE;
156
157 if (shutdown_signal) {
158 // We got signaled shutdown before we entered running state.
159 // Now that we've reached running state, shut'er down.
160 isc_app_ctxsuspend(dhcp_gbl_ctx.actx);
161 }
162
163 isc_event_free(&event);
164}
165
98bf1607 166isc_result_t
61ef216b
SR
167dhcp_context_create(int flags,
168 struct in_addr *local4,
169 struct in6_addr *local6) {
98bf1607
SR
170 isc_result_t result;
171
61ef216b 172 if ((flags & DHCP_CONTEXT_PRE_DB) != 0) {
0cd94b5e
TM
173 dhcp_gbl_ctx.actx_started = ISC_FALSE;
174 dhcp_gbl_ctx.actx_running = ISC_FALSE;
175
61ef216b
SR
176 /*
177 * Set up the error messages, this isn't the right place
178 * for this call but it is convienent for now.
179 */
180 result = dhcp_result_register();
181 if (result != ISC_R_SUCCESS) {
182 log_fatal("register_table() %s: %u", "failed", result);
183 }
98bf1607 184
61ef216b 185 memset(&dhcp_gbl_ctx, 0, sizeof (dhcp_gbl_ctx));
f6b8f48d 186
61ef216b 187 isc_lib_register();
98bf1607 188
61ef216b
SR
189 /* get the current time for use as the random seed */
190 gettimeofday(&cur_tv, (struct timezone *)0);
191 isc_random_seed(cur_tv.tv_sec);
98bf1607 192
158a34fb
SR
193 /* we need to create the memory context before
194 * the lib inits in case we aren't doing NSUPDATE
195 * in which case dst needs a memory context
196 */
197 result = isc_mem_create(0, 0, &dhcp_gbl_ctx.mctx);
198 if (result != ISC_R_SUCCESS)
199 goto cleanup;
200
201
98bf1607 202#if defined (NSUPDATE)
61ef216b
SR
203 result = dns_lib_init();
204 if (result != ISC_R_SUCCESS)
205 goto cleanup;
650ae59e 206#else /* defined NSUPDATE */
61ef216b
SR
207 /* The dst library is inited as part of dns_lib_init, we don't
208 * need it if NSUPDATE is enabled */
209 result = dst_lib_init(dhcp_gbl_ctx.mctx, NULL, 0);
210 if (result != ISC_R_SUCCESS)
211 goto cleanup;
98bf1607 212
650ae59e 213#endif /* defined NSUPDATE */
61ef216b
SR
214
215 result = isc_appctx_create(dhcp_gbl_ctx.mctx,
216 &dhcp_gbl_ctx.actx);
217 if (result != ISC_R_SUCCESS)
218 goto cleanup;
219
61ef216b
SR
220 result = isc_taskmgr_createinctx(dhcp_gbl_ctx.mctx,
221 dhcp_gbl_ctx.actx,
222 1, 0,
223 &dhcp_gbl_ctx.taskmgr);
224 if (result != ISC_R_SUCCESS)
225 goto cleanup;
226
227 result = isc_socketmgr_createinctx(dhcp_gbl_ctx.mctx,
228 dhcp_gbl_ctx.actx,
229 &dhcp_gbl_ctx.socketmgr);
230 if (result != ISC_R_SUCCESS)
231 goto cleanup;
232
233 result = isc_timermgr_createinctx(dhcp_gbl_ctx.mctx,
234 dhcp_gbl_ctx.actx,
235 &dhcp_gbl_ctx.timermgr);
236 if (result != ISC_R_SUCCESS)
237 goto cleanup;
238
0cd94b5e
TM
239 result = isc_task_create(dhcp_gbl_ctx.taskmgr, 0,
240 &dhcp_gbl_ctx.task);
61ef216b
SR
241 if (result != ISC_R_SUCCESS)
242 goto cleanup;
0985d149
FD
243
244 result = isc_app_ctxstart(dhcp_gbl_ctx.actx);
245 if (result != ISC_R_SUCCESS)
0cd94b5e
TM
246 goto cleanup;
247
0985d149
FD
248 dhcp_gbl_ctx.actx_started = ISC_TRUE;
249
0cd94b5e
TM
250 // Install the onrun callback.
251 result = isc_app_ctxonrun(dhcp_gbl_ctx.actx, dhcp_gbl_ctx.mctx,
252 dhcp_gbl_ctx.task, set_ctx_running,
253 dhcp_gbl_ctx.actx);
254 if (result != ISC_R_SUCCESS)
255 goto cleanup;
256
0985d149
FD
257 /* Not all OSs support suppressing SIGPIPE through socket
258 * options, so set the sigal action to be ignore. This allows
259 * broken connections to fail gracefully with EPIPE on writes */
260 handle_signal(SIGPIPE, SIG_IGN);
261
262 /* Reset handlers installed by isc_app_ctxstart()
263 * to default for control-c and kill */
264 handle_signal(SIGINT, SIG_DFL);
265 handle_signal(SIGTERM, SIG_DFL);
61ef216b 266 }
98bf1607
SR
267
268#if defined (NSUPDATE)
61ef216b 269 if ((flags & DHCP_CONTEXT_POST_DB) != 0) {
ca22af89
TM
270 /* Setting addresses only.
271 * All real work will be done later on if needed to avoid
272 * listening on ddns port if client/server was compiled with
273 * ddns support but not using it. */
61ef216b 274 if (local4 != NULL) {
ca22af89
TM
275 dhcp_gbl_ctx.use_local4 = 1;
276 isc_sockaddr_fromin(&dhcp_gbl_ctx.local4_sockaddr,
277 local4, 0);
61ef216b 278 }
ca22af89 279
61ef216b 280 if (local6 != NULL) {
ca22af89
TM
281 dhcp_gbl_ctx.use_local6 = 1;
282 isc_sockaddr_fromin6(&dhcp_gbl_ctx.local6_sockaddr,
283 local6, 0);
61ef216b 284 }
98bf1607 285
ca22af89
TM
286 if (!(flags & DHCP_DNS_CLIENT_LAZY_INIT)) {
287 result = dns_client_init();
0ab4a716 288 }
61ef216b 289 }
650ae59e 290#endif /* defined NSUPDATE */
61ef216b 291
98bf1607
SR
292 return(ISC_R_SUCCESS);
293
294 cleanup:
d122accf
SR
295 /*
296 * Currently we don't try and cleanup, just return an error
297 * expecting that our caller will log the error and exit.
298 */
98bf1607
SR
299
300 return(result);
301}
302
f4bc8261
SR
303/*
304 * Convert a string name into the proper structure for the isc routines
305 *
306 * Previously we allowed names without a trailing '.' however the current
307 * dns and dst code requires the names to end in a period. If the
308 * name doesn't have a trailing period add one as part of creating
309 * the dns name.
310 */
311
98bf1607
SR
312isc_result_t
313dhcp_isc_name(unsigned char *namestr,
314 dns_fixedname_t *namefix,
315 dns_name_t **name)
316{
317 size_t namelen;
318 isc_buffer_t b;
319 isc_result_t result;
f4bc8261 320
f6b8f48d 321 namelen = strlen((char *)namestr);
98bf1607
SR
322 isc_buffer_init(&b, namestr, namelen);
323 isc_buffer_add(&b, namelen);
324 dns_fixedname_init(namefix);
325 *name = dns_fixedname_name(namefix);
f4bc8261 326 result = dns_name_fromtext(*name, &b, dns_rootname, 0, NULL);
98bf1607
SR
327 isc_buffer_invalidate(&b);
328 return(result);
329}
330
331isc_result_t
332isclib_make_dst_key(char *inname,
333 char *algorithm,
334 unsigned char *secret,
335 int length,
336 dst_key_t **dstkey)
337{
338 isc_result_t result;
339 dns_name_t *name;
340 dns_fixedname_t name0;
341 isc_buffer_t b;
3ffc07de 342 unsigned int algorithm_code;
98bf1607
SR
343
344 isc_buffer_init(&b, secret, length);
345 isc_buffer_add(&b, length);
346
3ffc07de
TM
347 if (strcasecmp(algorithm, DHCP_HMAC_MD5_NAME) == 0) {
348 algorithm_code = DST_ALG_HMACMD5;
349 } else if (strcasecmp(algorithm, DHCP_HMAC_SHA1_NAME) == 0) {
350 algorithm_code = DST_ALG_HMACSHA1;
351 } else if (strcasecmp(algorithm, DHCP_HMAC_SHA224_NAME) == 0) {
352 algorithm_code = DST_ALG_HMACSHA224;
353 } else if (strcasecmp(algorithm, DHCP_HMAC_SHA256_NAME) == 0) {
354 algorithm_code = DST_ALG_HMACSHA256;
355 } else if (strcasecmp(algorithm, DHCP_HMAC_SHA384_NAME) == 0) {
356 algorithm_code = DST_ALG_HMACSHA384;
357 } else if (strcasecmp(algorithm, DHCP_HMAC_SHA512_NAME) == 0) {
358 algorithm_code = DST_ALG_HMACSHA512;
359 } else {
98bf1607
SR
360 return(DHCP_R_INVALIDARG);
361 }
362
f4bc8261 363 result = dhcp_isc_name((unsigned char *)inname, &name0, &name);
98bf1607
SR
364 if (result != ISC_R_SUCCESS) {
365 return(result);
366 }
367
3ffc07de 368 return(dst_key_frombuffer(name, algorithm_code, DNS_KEYOWNER_ENTITY,
98bf1607
SR
369 DNS_KEYPROTO_DNSSEC, dns_rdataclass_in,
370 &b, dhcp_gbl_ctx.mctx, dstkey));
371}
372
47e8308d
SR
373/**
374 * signal handler that initiates server shutdown
375 *
376 * @param signal signal code that we received
377 */
378void dhcp_signal_handler(int signal) {
0cd94b5e 379 if (shutdown_signal != 0) {
0895c955
SR
380 /* Already in shutdown. */
381 return;
382 }
0cd94b5e 383
0895c955
SR
384 /* Possible race but does it matter? */
385 shutdown_signal = signal;
386
0cd94b5e
TM
387 /* If the application context is running tell it to shut down */
388 if (dhcp_gbl_ctx.actx_running == ISC_TRUE) {
389 (void) isc_app_ctxsuspend(dhcp_gbl_ctx.actx);
47e8308d
SR
390 }
391}
ca22af89 392
1c779d3b 393#if defined (NSUPDATE)
ca22af89
TM
394isc_result_t dns_client_init() {
395 isc_result_t result;
396 if (dhcp_gbl_ctx.dnsclient == NULL) {
397 result = dns_client_createx2(dhcp_gbl_ctx.mctx,
398 dhcp_gbl_ctx.actx,
399 dhcp_gbl_ctx.taskmgr,
400 dhcp_gbl_ctx.socketmgr,
401 dhcp_gbl_ctx.timermgr,
402 0,
403 &dhcp_gbl_ctx.dnsclient,
404 (dhcp_gbl_ctx.use_local4 ?
405 &dhcp_gbl_ctx.local4_sockaddr
406 : NULL),
407 (dhcp_gbl_ctx.use_local6 ?
408 &dhcp_gbl_ctx.local6_sockaddr
409 : NULL));
410
411 if (result != ISC_R_SUCCESS) {
412 log_error("Unable to create DNS client context:"
413 " result: %d", result);
414 return result;
415 }
416
417 /* If we can't set up the servers we may not be able to
418 * do DDNS but we should continue to try and perform
419 * our basic functions and let the user sort it out. */
420 result = dhcp_dns_client_setservers();
421 if (result != ISC_R_SUCCESS) {
422 log_error("Unable to set resolver from resolv.conf; "
423 "startup continuing but DDNS support "
424 "may be affected: result %d", result);
425 }
426 }
427
428 return ISC_R_SUCCESS;
429}
650ae59e 430#endif /* defined (NSUPDATE) */