diff options
-rw-r--r-- | Makefile | 2 | ||||
-rwxr-xr-x | configure | 35 | ||||
-rw-r--r-- | doc/bitlbee.schema | 71 | ||||
-rw-r--r-- | storage.c | 2 | ||||
-rw-r--r-- | storage_ldap.c | 177 |
5 files changed, 287 insertions, 0 deletions
@@ -13,6 +13,8 @@ objects = account.o bitlbee.o conf.o crypting.o help.o ini.o ipc.o irc.o irc_com headers = account.h bitlbee.h commands.h conf.h config.h crypting.h help.h ini.h ipc.h irc.h log.h nick.h query.h set.h sock.h storage.h url.h user.h protocols/http_client.h protocols/md5.h protocols/nogaim.h protocols/proxy.h protocols/sha.h protocols/ssl_client.h subdirs = protocols +objects += $(LDAP_OBJ) + # Expansion of variables subdirobjs = $(foreach dir,$(subdirs),$(dir)/$(dir).o) CFLAGS += -Wall @@ -27,6 +27,7 @@ yahoo=1 debug=0 strip=1 ipv6=1 +ldap=auto ssl=auto arch=`uname -s` @@ -63,6 +64,8 @@ Option Description Default --ipv6=0/1 IPv6 socket support $ipv6 +--ldap=0/1/auto LDAP support $ldap + --ssl=... SSL library to use (gnutls, nss, openssl, bogus, auto) $ssl EOF @@ -202,6 +205,20 @@ EOF fi; } +detect_ldap() +{ + if $PKG_CONFIG --version > /dev/null 2>/dev/null && $PKG_CONFIG ldb; then + cat<<EOF>>Makefile.settings +EFLAGS+=`$PKG_CONFIG --libs ldb` +CFLAGS+=`$PKG_CONFIG --cflags ldb` +EOF + ldap=1 + ret=1 + else + ret=0 + fi +} + if [ "$msn" = 1 -o "$jabber" = 1 ]; then if [ "$ssl" = "auto" ]; then detect_gnutls @@ -262,6 +279,18 @@ if [ "$msn" = 1 -o "$jabber" = 1 ]; then echo 'SSL_CLIENT=ssl_'$ssl'.o' >> Makefile.settings fi +if [ "$ldap" = "auto" ]; then + detect_ldap +fi + +if [ "$ldap" = 0 ]; then + echo "LDAP_OBJ=\# no ldap" >> Makefile.settings + echo "#undef LDAP" >> config.h +elif [ "$ldap" = 1 ]; then + echo "#define LDAP 1" >> config.h + echo "LDAP_OBJ=storage_ldap.o" >> Makefile.settings +fi + if [ "$strip" = 0 ]; then echo "STRIP=\# skip strip" >> Makefile.settings; else @@ -415,3 +444,9 @@ if [ -n "$protocols" ]; then else echo ' Building without IM-protocol support. We wish you a lot of fun...'; fi + +if [ "$ldap" = "0" ]; then + echo " LDAP storage backend disabled." +else + echo " LDAP storage backend enabled." +fi diff --git a/doc/bitlbee.schema b/doc/bitlbee.schema new file mode 100644 index 00000000..795f5854 --- /dev/null +++ b/doc/bitlbee.schema @@ -0,0 +1,71 @@ +## LDAP Schema file for BitlBee +## Copyright (C) 2006 Jelmer Vernooij <jelmer@samba.org> +## +## We need the following object classes and related attributes: +## +## bitlBeeBuddy: +## - nick +## - handle + +## each bitlBeeNick has zero or more bitlBeeAccount subentries +## and bitlBeeAccount entries contain zero or more bitlBeeBuddy entries + +## The admin needs to setup the LDAP server to: +## - allow anonymous users to auth against bitlBeeNick objects on the +## password field +## - allow anonymous users to create new objects that start with nick= +## - allow read/write for a user that is authenticated only to his/her own +## object and subentries + +## - userid +## - userPassword +## - setting (multiple values) +## depends: top, account + +#FIXME: Unique OID + +attributetype ( 1.3.6.1.4.1.7165.2.1.24 NAME 'bitlBeeAutoConnect' + DESC 'Autoconnect setting' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE ) + +#FIXME: Unique OID + +attributetype ( 1.3.6.1.4.1.7165.2.1.24 NAME 'bitlBeeAccountNo' + DESC 'Account number' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +#FIXME: Unique OID + +objectclass ( 1.3.6.1.4.1.7165.2.2.12 NAME 'bitlBeeAccount' SUP account STRUCTURAL + DESC 'BitlBee User Account ' + MUST ( userid, userPassword ) + MAY ( ) ) + +## bitlBeeAccount: +## - accountNo 1.3.6.1.4.1.1466.115.121.1.27 +## - protocol (msn, oscar, jabber, yahoo, ...) +## - username +## - password +## - server name +## - autoconnect (true/false) 1.3.6.1.4.1.1466.115.121.1.7 +## depends: top + +#FIXME: Unique OID +objectclass ( 1.3.6.1.4.1.7165.2.2.12 NAME 'bitlBeeIMAccount' SUP account STRUCTURAL + DESC 'BitlBee IM Account ' + MUST ( bitlBeeAccountNo, userid, userPassword ) + MAY ( host, bitlBeeAutoconnect ) ) + +#FIXME: Unique OID +objectclass ( 1.3.6.1.4.1.7165.2.2.12 NAME 'bitlBeeSetting' SUP top STRUCTURAL + DESC 'BitlBee Configuration Setting' + MUST ( bitlBeeSettingName ) + MAY ( bitlBeeSettingValue ) ) + +#FIXME: Unique OID +objectclass ( 1.3.6.1.4.1.7165.2.2.12 NAME 'bitlBeeBuddy' SUP top STRUCTURAL + DESC 'BitlBee Nick Mapping' + MUST ( bitlBeeBuddyHandle ) + MAY ( ircNick ) ) @@ -6,6 +6,8 @@ /* Support for multiple storage backends */ +/* Copyright (C) 2005 Jelmer Vernooij <jelmer@samba.org> */ + /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/storage_ldap.c b/storage_ldap.c new file mode 100644 index 00000000..4bc99de5 --- /dev/null +++ b/storage_ldap.c @@ -0,0 +1,177 @@ + /********************************************************************\ + * BitlBee -- An IRC to other IM-networks gateway * + * * + * Copyright 2002-2004 Wilmer van der Gaast and others * + \********************************************************************/ + +/* Storage backend that uses a LDAP database */ + +/* Copyright (C) 2006 Jelmer Vernooij <jelmer@samba.org> */ + +/* + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License with + the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL; + if not, write to the Free Software Foundation, Inc., 59 Temple Place, + Suite 330, Boston, MA 02111-1307 USA +*/ + +#define BITLBEE_CORE +#include "bitlbee.h" +#include <ldap.h> + +#define BB_LDAP_HOST "localhost" +#define BB_LDAP_BASE "" + +static char *nick_dn(const char *nick) +{ + return g_strdup_printf("bitlBeeNick=%s%s%s", nick, BB_LDAP_BASE?",":"", BB_LDAP_BASE?BB_LDAP_BASE:""); +} + +static storage_status_t nick_connect(const char *nick, const char *password, LDAP **ld) +{ + char *mydn; + int ret; + storage_status_t status; + *ld = ldap_init(BB_LDAP_HOST, LDAP_PORT); + + if (!ld) { + log_message( LOGLVL_WARNING, "Unable to connect to LDAP server at %s", BB_LDAP_HOST ); + return STORAGE_OTHER_ERROR; + } + + mydn = nick_dn(nick); + + ret = ldap_simple_bind_s(*ld, mydn, password); + + switch (ret) { + case LDAP_SUCCESS: status = STORAGE_OK; break; + case LDAP_INVALID_CREDENTIALS: status = STORAGE_INVALID_PASSWORD; break; + default: + log_message( LOGLVL_WARNING, "Unable to authenticate %s: %s", mydn, ldap_err2string(ret) ); + status = STORAGE_OTHER_ERROR; + break; + } + + g_free(mydn); + + return status; +} + +static storage_status_t sldap_load ( const char *my_nick, const char* password, irc_t *irc ) +{ + LDAPMessage *res, *msg; + LDAP *ld; + int ret, i; + storage_status_t status; + char *mydn; + + status = nick_connect(my_nick, password, &ld); + if (status != STORAGE_OK) + return status; + + mydn = nick_dn(my_nick); + + ret = ldap_search_s(ld, mydn, LDAP_SCOPE_BASE, "(objectClass=*)", NULL, 0, &res); + + if (ret != LDAP_SUCCESS) { + log_message( LOGLVL_WARNING, "Unable to search for %s: %s", mydn, ldap_err2string(ret) ); + ldap_unbind_s(ld); + return STORAGE_OTHER_ERROR; + } + + g_free(mydn); + + for (msg = ldap_first_entry(ld, res); msg; msg = ldap_next_entry(ld, msg)) { + } + + /* FIXME: Store in irc_t */ + + ldap_unbind_s(ld); + + return STORAGE_OK; +} + +static storage_status_t sldap_check_pass( const char *nick, const char *password ) +{ + LDAP *ld; + storage_status_t status; + + status = nick_connect(nick, password, &ld); + + ldap_unbind_s(ld); + + return status; +} + +static storage_status_t sldap_remove( const char *nick, const char *password ) +{ + storage_status_t status; + LDAP *ld; + char *mydn; + int ret; + + status = nick_connect(nick, password, &ld); + + if (status != STORAGE_OK) + return status; + + mydn = nick_dn(nick); + + ret = ldap_delete(ld, mydn); + + if (ret != LDAP_SUCCESS) { + log_message( LOGLVL_WARNING, "Error removing %s: %s", mydn, ldap_err2string(ret) ); + ldap_unbind_s(ld); + return STORAGE_OTHER_ERROR; + } + + ldap_unbind_s(ld); + + g_free(mydn); + return STORAGE_OK; +} + +static storage_status_t sldap_save( irc_t *irc, int overwrite ) +{ + LDAP *ld; + char *mydn; + storage_status_t status; + LDAPMessage *msg; + + status = nick_connect(irc->nick, irc->password, &ld); + if (status != STORAGE_OK) + return status; + + mydn = nick_dn(irc->nick); + + /* FIXME: Make this a bit more atomic? What if we crash after + * removing the old account but before adding the new one ? */ + if (overwrite) + sldap_remove(irc->nick, irc->password); + + g_free(mydn); + + ldap_unbind_s(ld); + + return STORAGE_OK; +} + + + +storage_t storage_ldap = { + .name = "ldap", + .check_pass = sldap_check_pass, + .remove = sldap_remove, + .load = sldap_load, + .save = sldap_save +}; |