1 /* Copyright (C) 2009-2014, Martin Johansson <martin@fatbob.nu>
2    Copyright (C) 2005-2014, Thorvald Natvig <thorvald@natvig.com>
3 
4    All rights reserved.
5 
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions
8    are met:
9 
10    - Redistributions of source code must retain the above copyright notice,
11      this list of conditions and the following disclaimer.
12    - Redistributions in binary form must reproduce the above copyright notice,
13      this list of conditions and the following disclaimer in the documentation
14      and/or other materials provided with the distribution.
15    - Neither the name of the Developers nor the names of its contributors may
16      be used to endorse or promote products derived from this software without
17      specific prior written permission.
18 
19    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
23    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include <libconfig.h>
36 
37 #include "types.h"
38 #include "conf.h"
39 #include "log.h"
40 
41 static config_t configuration;
42 
43 #define DEFAULT_WELCOME "Welcome to uMurmur!"
44 #define DEFAULT_MAX_CLIENTS 10
45 #define DEFAULT_MAX_BANDWIDTH 48000
46 #define DEFAULT_BINDPORT 64738
47 #define DEFAULT_BAN_LENGTH (60*60)
48 #define DEFAULT_OPUS_THRESHOLD 100
49 
50 const char defaultconfig[] = DEFAULT_CONFIG;
51 
52 void Conf_init(const char *conffile)
53 {
54 	config_init(&configuration);
55 	if (conffile == NULL)
56 		conffile = defaultconfig;
57 	if (config_read_file(&configuration, conffile) != CONFIG_TRUE) {
58 		Log_fatal("Error in config file %s line %d: %s", conffile,
59 			config_error_line(&configuration), config_error_text(&configuration));
60 	}
61 }
62 
63 bool_t Conf_ok(const char *conffile)
64 {
65 	bool_t rc = true;
66 	config_init(&configuration);
67 	if (conffile == NULL)
68 		conffile = defaultconfig;
69 	if (config_read_file(&configuration, conffile) != CONFIG_TRUE) {
70 		fprintf(stderr, "Error in config file %s line %d: %s\n", conffile,
71 			config_error_line(&configuration), config_error_text(&configuration));
72 		rc = false;
73 	}
74 	config_destroy(&configuration);
75 	return rc;
76 }
77 
78 void Conf_deinit()
79 {
80 	config_destroy(&configuration);
81 }
82 
83 const char *getStrConf(param_t param)
84 {
85 	config_setting_t *setting = NULL;
86 	const char *strsetting = NULL;
87 
88 	switch (param) {
89 		case CERTIFICATE:
90 			setting = config_lookup(&configuration, "certificate");
91 			if (!setting)
92 				return "/usr/local/etc/umurmur/certificate.crt";
93 			else {
94 				if ((strsetting = config_setting_get_string(setting)) != NULL)
95 					return strsetting;
96 				else
97 					return "/usr/local/etc/umurmur/certificate.crt";
98 			}
99 			break;
100 		case KEY:
101 			setting = config_lookup(&configuration, "private_key");
102 			if (!setting)
103 				return "/usr/local/etc/umurmur/private_key.key";
104 			else {
105 				if ((strsetting = config_setting_get_string(setting)) != NULL)
106 					return strsetting;
107 				else
108 					return "/usr/local/etc/umurmur/private_key.key";
109 			}
110 			break;
111 		case CAPATH:
112 			setting = config_lookup(&configuration, "ca_path");
113 			if (!setting)
114 				return NULL;
115 			else {
116 				if ((strsetting = config_setting_get_string(setting)) != NULL)
117 					return strsetting;
118 				else
119 					return NULL;
120 			}
121 			break;
122 		case PASSPHRASE:
123 			setting = config_lookup(&configuration, "password");
124 			if (!setting)
125 				return "";
126 			else {
127 				if ((strsetting = config_setting_get_string(setting)) != NULL)
128 					return strsetting;
129 				else
130 					return "";
131 			}
132 			break;
133 		case ADMIN_PASSPHRASE:
134 			setting = config_lookup(&configuration, "admin_password");
135 			if (!setting)
136 				return "";
137 			else {
138 				if ((strsetting = config_setting_get_string(setting)) != NULL)
139 					return strsetting;
140 				else
141 					return "";
142 			}
143 			break;
144 		case BINDADDR:
145 			setting = config_lookup(&configuration, "bindaddr");
146 			if (!setting)
147 				return NULL;
148 			else {
149 				if ((strsetting = config_setting_get_string(setting)) != NULL)
150 					return strsetting;
151 				else
152 					return NULL;
153 			}
154 			break;
155 		case BINDADDR6:
156 			setting = config_lookup(&configuration, "bindaddr6");
157 			if (!setting)
158 				return NULL;
159 			else {
160 				if ((strsetting = config_setting_get_string(setting)) != NULL)
161 					return strsetting;
162 				else
163 					return NULL;
164 			}
165 			break;
166 		case WELCOMETEXT:
167 			setting = config_lookup(&configuration, "welcometext");
168 			if (!setting)
169 				return DEFAULT_WELCOME;
170 			else {
171 				if ((strsetting = config_setting_get_string(setting)) != NULL)
172 					return strsetting;
173 				else
174 					return DEFAULT_WELCOME;
175 			}
176 			break;
177 		case DEFAULT_CHANNEL:
178 			setting = config_lookup(&configuration, "default_channel");
179 			if (!setting)
180 				return "";
181 			else {
182 				if ((strsetting = config_setting_get_string(setting)) != NULL)
183 					return strsetting;
184 				else
185 					return "";
186 			}
187 			break;
188 		case USERNAME:
189 			setting = config_lookup(&configuration, "username");
190 			if (!setting)
191 				return "";
192 			else {
193 				if ((strsetting = config_setting_get_string(setting)) != NULL)
194 					return strsetting;
195 				else
196 					return "";
197 			}
198 			break;
199 		case GROUPNAME:
200 			setting = config_lookup(&configuration, "groupname");
201 			if (!setting)
202 				return "";
203 			else {
204 				if ((strsetting = config_setting_get_string(setting)) != NULL)
205 					return strsetting;
206 				else
207 					return "";
208 			}
209 			break;
210 		case LOGFILE:
211 			setting = config_lookup(&configuration, "logfile");
212 			if (!setting)
213 				return NULL;
214 			else {
215 				if ((strsetting = config_setting_get_string(setting)) != NULL)
216 					return strsetting;
217 				else
218 					return NULL;
219 			}
220 			break;
221 		case BANFILE:
222 			setting = config_lookup(&configuration, "banfile");
223 			if (!setting)
224 				return NULL;
225 			else {
226 				if ((strsetting = config_setting_get_string(setting)) != NULL)
227 					return strsetting;
228 				else
229 					return NULL;
230 			}
231 			break;
232 		default:
233 			doAssert(false);
234 			break;
235 	}
236 	return NULL;
237 }
238 
239 int getIntConf(param_t param)
240 {
241 	config_setting_t *setting = NULL;
242 
243 	switch (param) {
244 		case BINDPORT:
245 			setting = config_lookup(&configuration, "bindport");
246 			if (!setting)
247 				return DEFAULT_BINDPORT;
248 			else {
249 				return config_setting_get_int(setting);
250 			}
251 			break;
252 		case BINDPORT6:
253 			setting = config_lookup(&configuration, "bindport6");
254 			if (!setting)
255 				/* If bindport6 is not specified, we default
256 				 * to whatever bindport is, rather than always
257 				 * default to 64738 */
258 				return getIntConf(BINDPORT);
259 			else {
260 				return config_setting_get_int(setting);
261 			}
262 			break;
263 		case BAN_LENGTH:
264 			setting = config_lookup(&configuration, "ban_length");
265 			if (!setting)
266 				return DEFAULT_BAN_LENGTH;
267 			else {
268 				return config_setting_get_int(setting);
269 			}
270 			break;
271 		case MAX_BANDWIDTH:
272 			setting = config_lookup(&configuration, "max_bandwidth");
273 			if (!setting)
274 				return DEFAULT_MAX_BANDWIDTH;
275 			else {
276 				return config_setting_get_int(setting);
277 			}
278 			break;
279 		case MAX_CLIENTS:
280 			setting = config_lookup(&configuration, "max_users");
281 			if (!setting)
282 				return DEFAULT_MAX_CLIENTS;
283 			else {
284 				return config_setting_get_int(setting);
285 			}
286 			break;
287 		case OPUS_THRESHOLD:
288 			setting = config_lookup(&configuration, "opus_threshold");
289 			if (!setting)
290 				return DEFAULT_OPUS_THRESHOLD;
291 			else {
292 				return config_setting_get_int(setting);
293 			}
294 			break;
295 		default:
296 			doAssert(false);
297 	}
298 }
299 
300 bool_t getBoolConf(param_t param)
301 {
302 	config_setting_t *setting = NULL;
303 
304 	switch (param) {
305 		case ALLOW_TEXTMESSAGE:
306 			setting = config_lookup(&configuration, "allow_textmessage");
307 			if (!setting)
308 				return true;
309 			else
310 				return config_setting_get_bool(setting);
311 			break;
312 		case ENABLE_BAN:
313 			setting = config_lookup(&configuration, "enable_ban");
314 			if (!setting)
315 				return false;
316 			else
317 				return config_setting_get_bool(setting);
318 			break;
319 		case SYNC_BANFILE:
320 			setting = config_lookup(&configuration, "sync_banfile");
321 			if (!setting)
322 				return false;
323 			else
324 				return config_setting_get_bool(setting);
325 			break;
326 		case SHOW_ADDRESSES:
327 			setting = config_lookup(&configuration, "show_addresses");
328 			if (!setting)
329 				return true;
330 			else
331 				return config_setting_get_bool(setting);
332 			break;
333 		default:
334 			doAssert(false);
335 	}
336 }
337 
338 int Conf_getNextChannel(conf_channel_t *chdesc, int index)
339 {
340 	config_setting_t *setting = NULL;
341 	int maxconfig = 64, ret = 0;
342 	char configstr[maxconfig];
343 
344 	ret = snprintf(configstr, maxconfig, "channels.[%d].name", index);
345 	setting = config_lookup(&configuration, configstr);
346 	if (ret >= maxconfig || ret < 0 || setting == NULL)
347 		return -1; /* Required */
348 	chdesc->name =  config_setting_get_string(setting);
349 
350 	ret = snprintf(configstr, maxconfig, "channels.[%d].parent", index);
351 	setting = config_lookup(&configuration, configstr);
352 	if (ret >= maxconfig || ret < 0 || setting == NULL)
353 		return -1; /* Required */
354 	chdesc->parent = config_setting_get_string(setting);
355 
356 	ret = snprintf(configstr, maxconfig, "channels.[%d].description", index);
357 	setting = config_lookup(&configuration, configstr);
358 	if (ret >= maxconfig || ret < 0 || setting == NULL) /* Optional */
359 		chdesc->description = NULL;
360 	else
361 		chdesc->description = config_setting_get_string(setting);
362 
363 	ret = snprintf(configstr, maxconfig, "channels.[%d].password", index);
364 	setting = config_lookup(&configuration, configstr);
365 	if (ret >= maxconfig || ret < 0 || setting == NULL) /* Optional */
366 		chdesc->password = NULL;
367 	else
368 		chdesc->password = config_setting_get_string(setting);
369 
370 	ret = snprintf(configstr, maxconfig, "channels.[%d].noenter", index);
371 	setting = config_lookup(&configuration, configstr);
372 	if (ret >= maxconfig || ret < 0 || setting == NULL) /* Optional */
373 		chdesc->noenter = false;
374 	else
375 		chdesc->noenter = config_setting_get_bool(setting);
376 
377 	ret = snprintf(configstr, maxconfig, "channels.[%d].silent", index);
378 	setting = config_lookup(&configuration, configstr);
379 	if (ret >= maxconfig || ret < 0 || setting == NULL) /* Optional */
380 		chdesc->silent = false;
381 	else
382 		chdesc->silent = config_setting_get_bool(setting);
383 
384 	ret = snprintf(configstr, maxconfig, "channels.[%d].position", index);
385 	setting = config_lookup(&configuration, configstr);
386 	if (ret >= maxconfig || ret < 0 || setting == NULL) /* Optional */
387 		chdesc->position = 0;
388 	else
389 		chdesc->position = config_setting_get_int(setting);
390 
391 	return 0;
392 }
393 
394 int Conf_getNextChannelLink(conf_channel_link_t *chlink, int index)
395 {
396 	config_setting_t *setting = NULL;
397 	int maxconfig = 64, ret = 0;
398 	char configstr[maxconfig];
399 
400 	ret = snprintf(configstr, maxconfig, "channel_links.[%d].source", index);
401 	setting = config_lookup(&configuration, configstr);
402 	if (ret >= maxconfig || ret < 0 || setting == NULL)
403 		return -1;
404 	chlink->source = config_setting_get_string(setting);
405 
406 	ret = snprintf(configstr, maxconfig, "channel_links.[%d].destination", index);
407 	setting = config_lookup(&configuration, configstr);
408 	if (ret >= maxconfig || ret < 0 || setting == NULL)
409 		return -1;
410 	chlink->destination = config_setting_get_string(setting);
411 
412 	return 0;
413 }
414