source: conf.c @ 4fe91a1

Last change on this file since 4fe91a1 was 50bb490, checked in by Dennis Kaarsemaker <dennis@…>, at 2016-03-25T18:07:53Z

ldap authentication backend

We only support the openldap scheme for now, with users that are
posixAccounts. Moreover, as the plugin cannot be configured directly,
you must configure libldap correctly in /etc/openldap/ldap.conf

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