source: storage.c @ f95e606

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

Authentication: scaffolding for multiple authentication backends

Instead of always putting users passwords in XML files, allow site
admins to configure a different authentication method to integrate
authentication with other systems.

This doesn't add any authentication backends yet, merely the
scaffolding. Notably:

  • Password checking and loading/removing from storage has been decoupled. A new auth_check_pass function is used to check passwords. It does check against the configured storage first, but will handle the authentication backends as well. The XML storage merely signals that a user's password should be checked using an authentication backend.
  • If unknown-to-bitlbee users identify using an authentication backend, they are automatically registered.
  • If an authentication backend is used, that fact is stored in the XML file, the password is not. Passwords are also stored unencrypted in this case, as the password used to encrypt them can change underneath us.
  • configure and Makefile changes for the backend objects
  • Property mode set to 100644
File size: 4.6 KB
RevLine 
[5ebff60]1/********************************************************************\
[1ee6c18]2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2004 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
7/* Support for multiple storage backends */
8
[d9d36fc]9/* Copyright (C) 2005 Jelmer Vernooij <jelmer@samba.org> */
10
[1ee6c18]11/*
12  This program is free software; you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation; either version 2 of the License, or
15  (at your option) any later version.
16
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  GNU General Public License for more details.
21
22  You should have received a copy of the GNU General Public License with
23  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
[6f10697]24  if not, write to the Free Software Foundation, Inc., 51 Franklin St.,
25  Fifth Floor, Boston, MA  02110-1301  USA
[1ee6c18]26*/
27
28#define BITLBEE_CORE
29#include "bitlbee.h"
30
[c121f89]31extern storage_t storage_xml;
[1ee6c18]32
[c121f89]33static GList *storage_backends = NULL;
[1ee6c18]34
35void register_storage_backend(storage_t *backend)
36{
37        storage_backends = g_list_append(storage_backends, backend);
38}
39
[b73ac9c]40static storage_t *storage_init_single(const char *name)
[1ee6c18]41{
42        GList *gl;
[b3c467b]43        storage_t *st = NULL;
[1ee6c18]44
45        for (gl = storage_backends; gl; gl = gl->next) {
46                st = gl->data;
[5ebff60]47                if (strcmp(st->name, name) == 0) {
[1ee6c18]48                        break;
[5ebff60]49                }
[1ee6c18]50        }
51
[5ebff60]52        if (gl == NULL) {
[1ee6c18]53                return NULL;
[5ebff60]54        }
[1ee6c18]55
[5ebff60]56        if (st->init) {
[1ee6c18]57                st->init();
[5ebff60]58        }
[1ee6c18]59
60        return st;
61}
[ab49fdc]62
[b73ac9c]63GList *storage_init(const char *primary, char **migrate)
64{
65        GList *ret = NULL;
66        int i;
67        storage_t *storage;
[5ebff60]68
[c121f89]69        register_storage_backend(&storage_xml);
[5ebff60]70
[b73ac9c]71        storage = storage_init_single(primary);
[5ebff60]72        if (storage == NULL && storage->save == NULL) {
[b73ac9c]73                return NULL;
[5ebff60]74        }
[b73ac9c]75
76        ret = g_list_append(ret, storage);
77
78        for (i = 0; migrate && migrate[i]; i++) {
79                storage = storage_init_single(migrate[i]);
[5ebff60]80
81                if (storage) {
[b73ac9c]82                        ret = g_list_append(ret, storage);
[5ebff60]83                }
[b73ac9c]84        }
85
86        return ret;
87}
88
[8e6ecfe]89storage_status_t storage_check_pass(irc_t *irc, const char *nick, const char *password)
[ab49fdc]90{
[b73ac9c]91        GList *gl;
[5ebff60]92
[b73ac9c]93        /* Loop until we don't get NO_SUCH_USER */
94
95        for (gl = global.storage; gl; gl = gl->next) {
96                storage_t *st = gl->data;
97                storage_status_t status;
98
[8e6ecfe]99                status = st->check_pass(irc, nick, password);
[5ebff60]100                if (status != STORAGE_NO_SUCH_USER) {
[b73ac9c]101                        return status;
[5ebff60]102                }
[b73ac9c]103        }
[5ebff60]104
[b73ac9c]105        return STORAGE_NO_SUCH_USER;
[ab49fdc]106}
107
[5ebff60]108storage_status_t storage_load(irc_t * irc, const char *password)
[ab49fdc]109{
[b73ac9c]110        GList *gl;
[5ebff60]111
112        if (irc && irc->status & USTATUS_IDENTIFIED) {
[3183c21]113                return STORAGE_OTHER_ERROR;
[5ebff60]114        }
115
[b73ac9c]116        /* Loop until we don't get NO_SUCH_USER */
117        for (gl = global.storage; gl; gl = gl->next) {
118                storage_t *st = gl->data;
119                storage_status_t status;
120
[3183c21]121                status = st->load(irc, password);
[5ebff60]122                if (status == STORAGE_OK) {
[2dcaf9a]123                        GSList *l;
[5ebff60]124                        for (l = irc_plugins; l; l = l->next) {
[2dcaf9a]125                                irc_plugin_t *p = l->data;
[5ebff60]126                                if (p->storage_load) {
127                                        p->storage_load(irc);
128                                }
[2dcaf9a]129                        }
[b73ac9c]130                        return status;
[2dcaf9a]131                }
[5ebff60]132
133                if (status != STORAGE_NO_SUCH_USER) {
[b73ac9c]134                        return status;
[5ebff60]135                }
[b73ac9c]136        }
[5ebff60]137
[b73ac9c]138        return STORAGE_NO_SUCH_USER;
[ab49fdc]139}
140
[5ebff60]141storage_status_t storage_save(irc_t *irc, char *password, int overwrite)
[ab49fdc]142{
[3183c21]143        storage_status_t st;
[2dcaf9a]144        GSList *l;
[5ebff60]145
[3183c21]146        if (password != NULL) {
147                /* Should only use this in the "register" command. */
[5ebff60]148                if (irc->password || overwrite) {
[3183c21]149                        return STORAGE_OTHER_ERROR;
[5ebff60]150                }
151
[3183c21]152                irc_setpass(irc, password);
153        } else if ((irc->status & USTATUS_IDENTIFIED) == 0) {
154                return STORAGE_NO_SUCH_USER;
155        }
[5ebff60]156
157        st = ((storage_t *) global.storage->data)->save(irc, overwrite);
158
159        for (l = irc_plugins; l; l = l->next) {
[2dcaf9a]160                irc_plugin_t *p = l->data;
[5ebff60]161                if (p->storage_save) {
162                        p->storage_save(irc);
163                }
[2dcaf9a]164        }
[5ebff60]165
[3183c21]166        if (password != NULL) {
167                irc_setpass(irc, NULL);
168        }
[5ebff60]169
[3183c21]170        return st;
[ab49fdc]171}
172
[8e6ecfe]173storage_status_t storage_remove(const char *nick)
[ab49fdc]174{
[b73ac9c]175        GList *gl;
176        storage_status_t ret = STORAGE_OK;
[2dcaf9a]177        gboolean ok = FALSE;
178        GSList *l;
[5ebff60]179
180        /* Remove this account from all storage backends. If this isn't
181         * done, the account will still be usable, it'd just be
[b73ac9c]182         * loaded from a different backend. */
183        for (gl = global.storage; gl; gl = gl->next) {
184                storage_t *st = gl->data;
185                storage_status_t status;
186
[8e6ecfe]187                status = st->remove(nick);
[2dcaf9a]188                ok |= status == STORAGE_OK;
[5ebff60]189                if (status != STORAGE_NO_SUCH_USER && status != STORAGE_OK) {
[b73ac9c]190                        ret = status;
[5ebff60]191                }
[b73ac9c]192        }
[5ebff60]193
[2dcaf9a]194        /* If at least one succeeded, remove plugin data. */
[5ebff60]195        if (ok) {
196                for (l = irc_plugins; l; l = l->next) {
[2dcaf9a]197                        irc_plugin_t *p = l->data;
[5ebff60]198                        if (p->storage_remove) {
199                                p->storage_remove(nick);
200                        }
[2dcaf9a]201                }
[5ebff60]202        }
203
[b73ac9c]204        return ret;
[ab49fdc]205}
Note: See TracBrowser for help on using the repository browser.