source: conf.c @ 446a23e

Last change on this file since 446a23e was 446a23e, checked in by Dennis Kaarsemaker <dennis@…>, at 2016-03-23T06:44:13Z

Add a setting to disable 'account add'

In a locked down bitlbee instance it is useful to disable the 'account
add' command.

  • Property mode set to 100644
File size: 12.0 KB
Line 
1/********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2005 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
7/* Configuration reading code                                           */
8
9/*
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License with
21  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
22  if not, write to the Free Software Foundation, Inc., 51 Franklin St.,
23  Fifth Floor, Boston, MA  02110-1301  USA
24*/
25
26#include "bitlbee.h"
27
28#include <stdio.h>
29#include <string.h>
30#include <stdlib.h>
31#include "conf.h"
32#include "ini.h"
33#include "url.h"
34#include "ipc.h"
35
36#include "proxy.h"
37
38static int conf_loadini(conf_t *conf, char *file);
39static void conf_free(conf_t *conf);
40
41conf_t *conf_load(int argc, char *argv[])
42{
43        conf_t *conf;
44        int opt, i, config_missing = 0;
45
46        conf = g_new0(conf_t, 1);
47
48        conf->iface_in = NULL;
49        conf->iface_out = NULL;
50        conf->port = g_strdup("6667");
51        conf->nofork = 0;
52        conf->verbose = 0;
53        conf->primary_storage = g_strdup("xml");
54        conf->migrate_storage = g_strsplit("text", ",", -1);
55        conf->runmode = RUNMODE_INETD;
56        conf->authmode = AUTHMODE_OPEN;
57        conf->auth_pass = NULL;
58        conf->oper_pass = NULL;
59        conf->allow_account_add = 1;
60        conf->configdir = g_strdup(CONFIG);
61        conf->plugindir = g_strdup(PLUGINDIR);
62        conf->pidfile = g_strdup(PIDFILE);
63        conf->motdfile = g_strdup(ETCDIR "/motd.txt");
64        conf->ping_interval = 180;
65        conf->ping_timeout = 300;
66        conf->user = NULL;
67        conf->ft_max_size = SIZE_MAX;
68        conf->ft_max_kbps = G_MAXUINT;
69        conf->ft_listen = NULL;
70        conf->protocols = NULL;
71        conf->cafile = NULL;
72        proxytype = 0;
73
74        i = conf_loadini(conf, global.conf_file);
75        if (i == 0) {
76                fprintf(stderr, "Error: Syntax error in configuration file `%s'.\n", global.conf_file);
77                conf_free(conf);
78                return NULL;
79        } else if (i == -1) {
80                config_missing++;
81                /* Whine after parsing the options if there was no -c pointing
82                   at a *valid* configuration file. */
83        }
84
85        while (argc > 0 && (opt = getopt(argc, argv, "i:p:P:nvIDFc:d:hu:V")) >= 0) {
86                /*     ^^^^ Just to make sure we skip this step from the REHASH handler. */
87                if (opt == 'i') {
88                        conf->iface_in = g_strdup(optarg);
89                } else if (opt == 'p') {
90                        g_free(conf->port);
91                        conf->port = g_strdup(optarg);
92                } else if (opt == 'P') {
93                        g_free(conf->pidfile);
94                        conf->pidfile = g_strdup(optarg);
95                } else if (opt == 'n') {
96                        conf->nofork = 1;
97                } else if (opt == 'v') {
98                        conf->verbose = 1;
99                } else if (opt == 'I') {
100                        conf->runmode = RUNMODE_INETD;
101                } else if (opt == 'D') {
102                        conf->runmode = RUNMODE_DAEMON;
103                } else if (opt == 'F') {
104                        conf->runmode = RUNMODE_FORKDAEMON;
105                } else if (opt == 'c') {
106                        if (strcmp(global.conf_file, optarg) != 0) {
107                                g_free(global.conf_file);
108                                global.conf_file = g_strdup(optarg);
109                                conf_free(conf);
110                                /* Re-evaluate arguments. Don't use this option twice,
111                                   you'll end up in an infinite loop! Hope this trick
112                                   works with all libcs BTW.. */
113                                optind = 1;
114                                return conf_load(argc, argv);
115                        }
116                } else if (opt == 'd') {
117                        g_free(conf->configdir);
118                        conf->configdir = g_strdup(optarg);
119                } else if (opt == 'h') {
120                        printf("Usage: bitlbee [-D/-F [-i <interface>] [-p <port>] [-n] [-v]] [-I]\n"
121                               "               [-c <file>] [-d <dir>] [-x] [-h]\n"
122                               "\n"
123                               "An IRC-to-other-chat-networks gateway\n"
124                               "\n"
125                               "  -I  Classic/InetD mode. (Default)\n"
126                               "  -D  Daemon mode. (one process serves all)\n"
127                               "  -F  Forking daemon. (one process per client)\n"
128                               "  -u  Run daemon as specified user.\n"
129                               "  -P  Specify PID-file (not for inetd mode)\n"
130                               "  -i  Specify the interface (by IP address) to listen on.\n"
131                               "      (Default: 0.0.0.0 (any interface))\n"
132                               "  -p  Port number to listen on. (Default: 6667)\n"
133                               "  -n  Don't fork.\n"
134                               "  -v  Be verbose (only works in combination with -n)\n"
135                               "  -c  Load alternative configuration file\n"
136                               "  -d  Specify alternative user configuration directory\n"
137                               "  -x  Command-line interface to password encryption/hashing\n"
138                               "  -h  Show this help page.\n"
139                               "  -V  Show version info.\n");
140                        conf_free(conf);
141                        return NULL;
142                } else if (opt == 'V') {
143                        printf("BitlBee %s\nAPI version %06x\nConfigure args: %s\n",
144                               BITLBEE_VERSION, BITLBEE_VERSION_CODE, BITLBEE_CONFIGURE_ARGS);
145                        conf_free(conf);
146                        return NULL;
147                } else if (opt == 'u') {
148                        g_free(conf->user);
149                        conf->user = g_strdup(optarg);
150                }
151        }
152
153        if (conf->configdir[strlen(conf->configdir) - 1] != '/') {
154                char *s = g_new(char, strlen(conf->configdir) + 2);
155
156                sprintf(s, "%s/", conf->configdir);
157                g_free(conf->configdir);
158                conf->configdir = s;
159        }
160
161        if (config_missing) {
162                fprintf(stderr, "Warning: Unable to read configuration file `%s'.\n", global.conf_file);
163        }
164
165        if (conf->cafile && access(conf->cafile, R_OK) != 0) {
166                /* Let's treat this as a serious problem so people won't think
167                   they're secure when in fact they're not. */
168                fprintf(stderr, "Error: Could not read CA file %s: %s\n", conf->cafile, strerror(errno));
169                conf_free(conf);
170                return NULL;
171        }
172
173        return conf;
174}
175
176static void conf_free(conf_t *conf)
177{
178        /* Free software means users have the four essential freedoms:
179           0. to run the program,
180           2. to study and change the program in source code form,
181           2. to redistribute exact copies, and
182           3. to distribute modified versions
183        */
184        g_free(conf->auth_pass);
185        g_free(conf->cafile);
186        g_free(conf->configdir);
187        g_free(conf->ft_listen);
188        g_free(conf->hostname);
189        g_free(conf->iface_in);
190        g_free(conf->iface_out);
191        g_free(conf->motdfile);
192        g_free(conf->oper_pass);
193        g_free(conf->pidfile);
194        g_free(conf->plugindir);
195        g_free(conf->port);
196        g_free(conf->primary_storage);
197        g_free(conf->user);
198        g_strfreev(conf->migrate_storage);
199        g_strfreev(conf->protocols);
200        g_free(conf);
201
202}
203
204static int conf_loadini(conf_t *conf, char *file)
205{
206        ini_t *ini;
207        int i;
208
209        ini = ini_open(file);
210        if (ini == NULL) {
211                return -1;
212        }
213        while (ini_read(ini)) {
214                if (g_strcasecmp(ini->section, "settings") == 0) {
215                        if (g_strcasecmp(ini->key, "runmode") == 0) {
216                                if (g_strcasecmp(ini->value, "daemon") == 0) {
217                                        conf->runmode = RUNMODE_DAEMON;
218                                } else if (g_strcasecmp(ini->value, "forkdaemon") == 0) {
219                                        conf->runmode = RUNMODE_FORKDAEMON;
220                                } else {
221                                        conf->runmode = RUNMODE_INETD;
222                                }
223                        } else if (g_strcasecmp(ini->key, "pidfile") == 0) {
224                                g_free(conf->pidfile);
225                                conf->pidfile = g_strdup(ini->value);
226                        } else if (g_strcasecmp(ini->key, "daemoninterface") == 0) {
227                                g_free(conf->iface_in);
228                                conf->iface_in = g_strdup(ini->value);
229                        } else if (g_strcasecmp(ini->key, "daemonport") == 0) {
230                                g_free(conf->port);
231                                conf->port = g_strdup(ini->value);
232                        } else if (g_strcasecmp(ini->key, "clientinterface") == 0) {
233                                g_free(conf->iface_out);
234                                conf->iface_out = g_strdup(ini->value);
235                        } else if (g_strcasecmp(ini->key, "authmode") == 0) {
236                                if (g_strcasecmp(ini->value, "registered") == 0) {
237                                        conf->authmode = AUTHMODE_REGISTERED;
238                                } else if (g_strcasecmp(ini->value, "closed") == 0) {
239                                        conf->authmode = AUTHMODE_CLOSED;
240                                } else {
241                                        conf->authmode = AUTHMODE_OPEN;
242                                }
243                        } else if (g_strcasecmp(ini->key, "authpassword") == 0) {
244                                g_free(conf->auth_pass);
245                                conf->auth_pass = g_strdup(ini->value);
246                        } else if (g_strcasecmp(ini->key, "operpassword") == 0) {
247                                g_free(conf->oper_pass);
248                                conf->oper_pass = g_strdup(ini->value);
249                        } else if (g_strcasecmp(ini->key, "allowaccountadd") == 0) {
250                                if (!is_bool(ini->value)) {
251                                        fprintf(stderr, "Invalid %s value: %s\n", ini->key, ini->value);
252                                        return 0;
253                                }
254                                conf->allow_account_add = bool2int(ini->value);
255                        } else if (g_strcasecmp(ini->key, "hostname") == 0) {
256                                g_free(conf->hostname);
257                                conf->hostname = g_strdup(ini->value);
258                        } else if (g_strcasecmp(ini->key, "configdir") == 0) {
259                                g_free(conf->configdir);
260                                conf->configdir = g_strdup(ini->value);
261                        } else if (g_strcasecmp(ini->key, "plugindir") == 0) {
262                                g_free(conf->plugindir);
263                                conf->plugindir = g_strdup(ini->value);
264                        } else if (g_strcasecmp(ini->key, "motdfile") == 0) {
265                                g_free(conf->motdfile);
266                                conf->motdfile = g_strdup(ini->value);
267                        } else if (g_strcasecmp(ini->key, "account_storage") == 0) {
268                                g_free(conf->primary_storage);
269                                conf->primary_storage = g_strdup(ini->value);
270                        } else if (g_strcasecmp(ini->key, "account_storage_migrate") == 0) {
271                                g_strfreev(conf->migrate_storage);
272                                conf->migrate_storage = g_strsplit_set(ini->value, " \t,;", -1);
273                        } else if (g_strcasecmp(ini->key, "pinginterval") == 0) {
274                                if (sscanf(ini->value, "%d", &i) != 1) {
275                                        fprintf(stderr, "Invalid %s value: %s\n", ini->key, ini->value);
276                                        return 0;
277                                }
278                                conf->ping_interval = i;
279                        } else if (g_strcasecmp(ini->key, "pingtimeout") == 0) {
280                                if (sscanf(ini->value, "%d", &i) != 1) {
281                                        fprintf(stderr, "Invalid %s value: %s\n", ini->key, ini->value);
282                                        return 0;
283                                }
284                                conf->ping_timeout = i;
285                        } else if (g_strcasecmp(ini->key, "proxy") == 0) {
286                                url_t *url = g_new0(url_t, 1);
287
288                                if (!url_set(url, ini->value)) {
289                                        fprintf(stderr, "Invalid %s value: %s\n", ini->key, ini->value);
290                                        g_free(url);
291                                        return 0;
292                                }
293
294                                strncpy(proxyhost, url->host, sizeof(proxyhost));
295                                strncpy(proxyuser, url->user, sizeof(proxyuser));
296                                strncpy(proxypass, url->pass, sizeof(proxypass));
297                                proxyport = url->port;
298                                if (url->proto == PROTO_HTTP) {
299                                        proxytype = PROXY_HTTP;
300                                } else if (url->proto == PROTO_SOCKS4) {
301                                        proxytype = PROXY_SOCKS4;
302                                } else if (url->proto == PROTO_SOCKS5) {
303                                        proxytype = PROXY_SOCKS5;
304                                } else if (url->proto == PROTO_SOCKS4A) {
305                                        proxytype = PROXY_SOCKS4A;
306                                }
307
308                                g_free(url);
309                        } else if (g_strcasecmp(ini->key, "user") == 0) {
310                                g_free(conf->user);
311                                conf->user = g_strdup(ini->value);
312                        } else if (g_strcasecmp(ini->key, "ft_max_size") == 0) {
313                                size_t ft_max_size;
314                                if (sscanf(ini->value, "%zu", &ft_max_size) != 1) {
315                                        fprintf(stderr, "Invalid %s value: %s\n", ini->key, ini->value);
316                                        return 0;
317                                }
318                                conf->ft_max_size = ft_max_size;
319                        } else if (g_strcasecmp(ini->key, "ft_max_kbps") == 0) {
320                                if (sscanf(ini->value, "%d", &i) != 1) {
321                                        fprintf(stderr, "Invalid %s value: %s\n", ini->key, ini->value);
322                                        return 0;
323                                }
324                                conf->ft_max_kbps = i;
325                        } else if (g_strcasecmp(ini->key, "ft_listen") == 0) {
326                                g_free(conf->ft_listen);
327                                conf->ft_listen = g_strdup(ini->value);
328                        } else if (g_strcasecmp(ini->key, "protocols") == 0) {
329                                g_strfreev(conf->protocols);
330                                conf->protocols = g_strsplit_set(ini->value, " \t,;", -1);
331                        } else if (g_strcasecmp(ini->key, "cafile") == 0) {
332                                g_free(conf->cafile);
333                                conf->cafile = g_strdup(ini->value);
334                        } else {
335                                fprintf(stderr, "Error: Unknown setting `%s` in configuration file (line %d).\n",
336                                        ini->key, ini->line);
337                                return 0;
338                                /* For now just ignore unknown keys... */
339                        }
340                } else if (g_strcasecmp(ini->section, "defaults") != 0) {
341                        fprintf(stderr, "Error: Unknown section [%s] in configuration file (line %d). "
342                                "BitlBee configuration must be put in a [settings] section!\n", ini->section,
343                                ini->line);
344                        return 0;
345                }
346        }
347        ini_close(ini);
348
349        return 1;
350}
351
352void conf_loaddefaults(irc_t *irc)
353{
354        ini_t *ini;
355
356        ini = ini_open(global.conf_file);
357        if (ini == NULL) {
358                return;
359        }
360        while (ini_read(ini)) {
361                if (g_strcasecmp(ini->section, "defaults") == 0) {
362                        set_t *s = set_find(&irc->b->set, ini->key);
363
364                        if (s) {
365                                if (s->def) {
366                                        g_free(s->def);
367                                }
368                                s->def = g_strdup(ini->value);
369                        }
370                }
371        }
372        ini_close(ini);
373}
Note: See TracBrowser for help on using the repository browser.