xref: /openbsd/usr.sbin/npppd/npppd/npppd_config.c (revision dbad4650)
1 /*	$OpenBSD: npppd_config.c,v 1.14 2015/01/19 01:48:59 deraadt Exp $ */
2 
3 /*-
4  * Copyright (c) 2009 Internet Initiative Japan Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 /* $Id: npppd_config.c,v 1.14 2015/01/19 01:48:59 deraadt Exp $ */
29 /*@file
30  * This file provides functions which operates configuration and so on.
31  */
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <net/if_dl.h>
35 #include <netinet/ip.h>
36 #include <net/route.h>
37 #include <arpa/inet.h>
38 #include <syslog.h>
39 #include <time.h>
40 #include <event.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <stdlib.h>
44 #include <stddef.h>
45 #include <errno.h>
46 
47 #include "addr_range.h"
48 #include "debugutil.h"
49 #include "npppd_subr.h"
50 #include "npppd_local.h"
51 #include "npppd_auth.h"
52 #include "npppd_iface.h"
53 #include "radish.h"
54 
55 #include "pathnames.h"
56 
57 #ifdef NPPPD_CONFIG_DEBUG
58 #define NPPPD_CONFIG_DBG(x) 	log_printf x
59 #define NPPPD_CONFIG_ASSERT(x) ASSERT(x)
60 #else
61 #define NPPPD_CONFIG_DBG(x)
62 #define NPPPD_CONFIG_ASSERT(x)
63 #endif
64 
65 static int              npppd_pool_load(npppd *);
66 static int              npppd_auth_realm_reload (npppd *);
67 static npppd_auth_base *realm_list_remove (slist *, const char *);
68 
69 int
npppd_config_check(const char * path)70 npppd_config_check(const char *path)
71 {
72 	struct npppd_conf  conf;
73 
74 	npppd_conf_init(&conf);
75 	return npppd_conf_parse(&conf, path);
76 }
77 
78 /***********************************************************************
79  * Reading the configuration. This is the export function which
80  * aggregates functions to read from each part.
81  ***********************************************************************/
82 /**
83  * reload the configuration file.
84  * @param   _this   pointer indicated to npppd
85  * @returns A 0 is returned if succeeds, otherwise non 0 is returned
86  *	    in case of configuration error.
87  */
88 int
npppd_reload_config(npppd * _this)89 npppd_reload_config(npppd *_this)
90 {
91 	int                retval = -1;
92 	struct npppd_conf  conf;
93 
94 	npppd_conf_init(&conf);
95 	if (npppd_conf_parse(&conf, _this->config_file) != 0) {
96 		log_printf(LOG_ERR, "Load configuration from='%s' failed",
97 		    _this->config_file);
98 		retval = -1;
99 		goto fail;
100 	}
101 
102 	_this->conf = conf;
103 
104 	retval = 0;
105 	log_printf(LOG_NOTICE, "Load configuration from='%s' successfully.",
106 	    _this->config_file);
107 
108 	/* FALLTHROUGH */
109 fail:
110 
111 	return retval;
112 }
113 
114 /** reload the configuration for each module */
115 int
npppd_modules_reload(npppd * _this)116 npppd_modules_reload(npppd *_this)
117 {
118 	int  rval;
119 
120 	rval = 0;
121 	if (npppd_pool_load(_this) != 0)
122 		return -1;
123 
124 	npppd_auth_realm_reload(_this);
125 #ifdef USE_NPPPD_L2TP
126 	rval |= l2tpd_reload(&_this->l2tpd, &_this->conf.l2tp_confs);
127 #endif
128 #ifdef USE_NPPPD_PPTP
129 	rval |= pptpd_reload(&_this->pptpd, &_this->conf.pptp_confs);
130 #endif
131 #ifdef USE_NPPPD_PPPOE
132 	rval |= pppoed_reload(&_this->pppoed, &_this->conf.pppoe_confs);
133 #endif
134 
135 	return rval;
136 }
137 
138 /***********************************************************************
139  * reload the configuration on each part
140  ***********************************************************************/
141 /** load the configuration for IP address pool */
142 static int
npppd_pool_load(npppd * _this)143 npppd_pool_load(npppd *_this)
144 {
145 	int n, i, j;
146 	npppd_pool pool0[NPPPD_MAX_IFACE];
147 	struct radish_head *rd_curr, *rd_new;
148 	struct ipcpconf *ipcp;
149 
150 	rd_curr = _this->rd;
151 	rd_new = NULL;
152 
153 	n = 0;
154 	if (!rd_inithead((void *)&rd_new, 0x41,
155 	    sizeof(struct sockaddr_npppd),
156 	    offsetof(struct sockaddr_npppd, snp_addr),
157 	    sizeof(struct in_addr), sockaddr_npppd_match)) {
158 		goto fail;
159 	}
160 	_this->rd = rd_new;
161 
162 	TAILQ_FOREACH(ipcp, &_this->conf.ipcpconfs, entry) {
163 		if (n >= countof(_this->pool)) {
164 			log_printf(LOG_WARNING, "number of the pool reached "
165 			    "limit=%d",(int)countof(_this->pool));
166 			break;
167 		}
168 		if (npppd_pool_init(&pool0[n], _this, ipcp->name) != 0) {
169 			log_printf(LOG_WARNING, "Failed to initialize "
170 			    "npppd_pool '%s': %m", ipcp->name);
171 			goto fail;
172 		}
173 		if (npppd_pool_reload(&pool0[n]) != 0)
174 			goto fail;
175 		n++;
176 	}
177 	for (; n < countof(pool0); n++)
178 		pool0[n].initialized = 0;
179 
180 	_this->rd = rd_curr;	/* backup */
181 	if (npppd_set_radish(_this, rd_new) != 0)
182 		goto fail;
183 
184 	for (i = 0; i < countof(_this->pool); i++) {
185 		if (_this->pool[i].initialized != 0)
186 			npppd_pool_uninit(&_this->pool[i]);
187 		if (pool0[i].initialized == 0)
188 			continue;
189 		_this->pool[i] = pool0[i];
190 		/* swap references */
191 		for (j = 0; j < _this->pool[i].addrs_size; j++) {
192 			if (_this->pool[i].initialized == 0)
193 				continue;
194 			_this->pool[i].addrs[j].snp_data_ptr = &_this->pool[i];
195 		}
196 	}
197 	log_printf(LOG_INFO, "Loading pool config successfully.");
198 
199 	return 0;
200 fail:
201 	/* rollback */
202 	for (i = 0; i < n; i++) {
203 		if (pool0[i].initialized != 0)
204 			npppd_pool_uninit(&pool0[i]);
205 	}
206 
207 	if (rd_curr != NULL)
208 		_this->rd = rd_curr;
209 
210 	if (rd_new != NULL) {
211 		rd_walktree(rd_new,
212 		    (int (*)(struct radish *, void *))rd_unlink,
213 		    rd_new->rdh_top);
214 		free(rd_new);
215 	}
216 	log_printf(LOG_NOTICE, "Loading pool config failed");
217 
218 	return 1;
219 }
220 
221 /* authentication realm */
222 static int
npppd_auth_realm_reload(npppd * _this)223 npppd_auth_realm_reload(npppd *_this)
224 {
225 	int              rval;
226 	slist            realms0, nrealms;
227 	struct authconf *auth;
228 	npppd_auth_base *auth_base;
229 
230 	rval = 0;
231 	slist_init(&realms0);
232 	slist_init(&nrealms);
233 
234 	if (slist_add_all(&realms0, &_this->realms) != 0) {
235 		log_printf(LOG_WARNING, "slist_add_all() failed in %s(): %m",
236 		__func__);
237 		goto fail;
238 	}
239 
240 	TAILQ_FOREACH(auth, &_this->conf.authconfs, entry) {
241 #ifndef USE_NPPPD_RADIUS
242 		if (auth->auth_type == NPPPD_AUTH_TYPE_RADIUS)  {
243 			log_printf(LOG_WARNING, "radius support is not "
244 			    "enabled by compile time.");
245 			continue;
246 		}
247 #endif
248 		auth_base = realm_list_remove(&realms0, auth->name);
249 		if (auth_base != NULL &&
250 		    npppd_auth_get_type(auth_base) != auth->auth_type) {
251 			/*
252 			 * The type of authentication has been changed in the
253 			 * same label name.
254 			 */
255 			slist_add(&realms0, auth_base);
256 			auth_base = NULL;
257 		}
258 
259 		if (auth_base == NULL) {
260 			/* create newly */
261 			if ((auth_base = npppd_auth_create(auth->auth_type,
262 			    auth->name, _this)) == NULL) {
263 				log_printf(LOG_WARNING, "npppd_auth_create() "
264 				    "failed in %s(): %m", __func__);
265 				goto fail;
266 			}
267 		}
268 		slist_add(&nrealms, auth_base);
269 	}
270 	if (slist_set_size(&_this->realms, slist_length(&nrealms)) != 0) {
271 		log_printf(LOG_WARNING, "slist_set_size() failed in %s(): %m",
272 		    __func__);
273 		goto fail;
274 	}
275 
276 	slist_itr_first(&realms0);
277 	while (slist_itr_has_next(&realms0)) {
278 		auth_base = slist_itr_next(&realms0);
279 		if (npppd_auth_is_disposing(auth_base))
280 			continue;
281 		npppd_auth_dispose(auth_base);
282 	}
283 
284 	slist_itr_first(&nrealms);
285 	while (slist_itr_has_next(&nrealms)) {
286 		auth_base = slist_itr_next(&nrealms);
287 		rval |= npppd_auth_reload(auth_base);
288 	}
289 	slist_remove_all(&_this->realms);
290 	(void)slist_add_all(&_this->realms, &nrealms);
291 	(void)slist_add_all(&_this->realms, &realms0);
292 
293 	slist_fini(&realms0);
294 	slist_fini(&nrealms);
295 
296 	return rval;
297 fail:
298 
299 	slist_itr_first(&nrealms);
300 	while (slist_itr_has_next(&nrealms)) {
301 		auth_base = slist_itr_next(&nrealms);
302 		npppd_auth_destroy(auth_base);
303 	}
304 	slist_fini(&realms0);
305 	slist_fini(&nrealms);
306 
307 	return 1;
308 }
309 
310 static npppd_auth_base *
realm_list_remove(slist * list0,const char * label)311 realm_list_remove(slist *list0, const char *label)
312 {
313 	npppd_auth_base *base;
314 
315 	for (slist_itr_first(list0); slist_itr_has_next(list0); ) {
316 		base = slist_itr_next(list0);
317 		if (npppd_auth_is_disposing(base))
318 			continue;
319 		if (strcmp(npppd_auth_get_name(base), label) == 0)
320 			return slist_itr_remove(list0);
321 	}
322 
323 	return NULL;
324 }
325 
326 /** load the interface configuration */
327 int
npppd_ifaces_load_config(npppd * _this)328 npppd_ifaces_load_config(npppd *_this)
329 {
330 	int           i;
331 	struct iface *iface;
332 	npppd_iface  *niface;
333 
334 	for (i = 0; i < countof(_this->iface); i++) {
335 		if (_this->iface[i].initialized == 0)
336 			continue;
337 		TAILQ_FOREACH(iface, &_this->conf.ifaces, entry) {
338 			if (strcmp(_this->iface[i].ifname, iface->name) == 0)
339 				break;
340 		}
341 		if (iface == NULL) {
342 			npppd_iface_stop(&_this->iface[i]);
343 			npppd_iface_fini(&_this->iface[i]);
344 		}
345 	}
346 	TAILQ_FOREACH(iface, &_this->conf.ifaces, entry) {
347 		/* find the existing entry or first free entry */
348 		niface = NULL;
349 		for (i = 0; i < countof(_this->iface); i++) {
350 			if (_this->iface[i].initialized == 0) {
351 				if (niface == NULL)
352 					niface = &_this->iface[i];
353 				continue;
354 			}
355 			if (strcmp(_this->iface[i].ifname, iface->name) == 0) {
356 				niface = &_this->iface[i];
357 				break;
358 			}
359 		}
360 		if (niface == NULL) {
361 			log_printf(LOG_WARNING,
362 			    "number of the interface reached limit=%d",
363 			    (int)countof(_this->iface));
364 			break;
365 		}
366 		if (niface->initialized == 0)
367 			npppd_iface_init(_this, niface, iface);
368 		else
369 			npppd_iface_reinit(niface, iface);
370 	}
371 
372 	return 0;
373 }
374