aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rwxr-xr-xconfigure46
-rw-r--r--doc/bitlbee.schema62
-rw-r--r--irc.c26
-rw-r--r--protocols/nogaim.c3
-rw-r--r--protocols/nogaim.h6
-rw-r--r--storage.c2
-rw-r--r--storage_ldap.c177
8 files changed, 316 insertions, 8 deletions
diff --git a/Makefile b/Makefile
index 51ffc83f..845beb1c 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/configure b/configure
index a3c16e75..b05aa155 100755
--- a/configure
+++ b/configure
@@ -30,6 +30,7 @@ strip=1
ipv6=1
events=glib
+ldap=auto
ssl=auto
arch=`uname -s`
@@ -66,6 +67,8 @@ Option Description Default
--ipv6=0/1 IPv6 socket support $ipv6
+--ldap=0/1/auto LDAP support $ldap
+
--events=... Event handler (glib, libevent) $events
--ssl=... SSL library to use (gnutls, nss, openssl, bogus, auto)
$ssl
@@ -145,16 +148,18 @@ echo CFLAGS+=-I`pwd` -I`pwd`/protocols -I. >> Makefile.settings
echo CFLAGS+=-DHAVE_CONFIG_H >> Makefile.settings
if [ -n "$CC" ]; then
- echo "CC=$CC" >> Makefile.settings;
+ CC=$CC
elif type gcc > /dev/null 2> /dev/null; then
- echo "CC=gcc" >> Makefile.settings;
+ CC=gcc
elif type cc > /dev/null 2> /dev/null; then
- echo "CC=cc" >> Makefile.settings;
+ CC=cc
else
echo 'Cannot find a C compiler, aborting.'
exit 1;
fi
+echo "CC=$CC" >> Makefile.settings;
+
if [ -n "$LD" ]; then
echo "LD=$LD" >> Makefile.settings;
elif type ld > /dev/null 2> /dev/null; then
@@ -231,6 +236,23 @@ EOF
fi;
}
+detect_ldap()
+{
+ TMPFILE=`mktemp`
+ if $CC -o $TMPFILE -shared -lldap 2>/dev/null >/dev/null; then
+ cat<<EOF>>Makefile.settings
+EFLAGS+=-lldap
+CFLAGS+=
+EOF
+ ldap=1
+ rm -f $TMPFILE
+ ret=1
+ else
+ ldap=0
+ ret=0
+ fi
+}
+
if [ "$msn" = 1 -o "$jabber" = 1 ]; then
if [ "$ssl" = "auto" ]; then
detect_gnutls
@@ -291,6 +313,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 WITH_LDAP" >> config.h
+elif [ "$ldap" = 1 ]; then
+ echo "#define WITH_LDAP 1" >> config.h
+ echo "LDAP_OBJ=storage_ldap.o" >> Makefile.settings
+fi
+
if [ "$strip" = 0 ]; then
echo "STRIP=\# skip strip" >> Makefile.settings;
else
@@ -443,3 +477,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..3322e057
--- /dev/null
+++ b/doc/bitlbee.schema
@@ -0,0 +1,62 @@
+## 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
+
+attributetype ( 1.3.6.1.4.1.25873.2.1.1 NAME 'bitlBeeAutoConnect'
+ DESC 'Autoconnect setting'
+ EQUALITY booleanMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.25873.2.1.2 NAME 'bitlBeeAccountNo'
+ DESC 'Account number'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+objectclass ( 1.3.6.1.4.1.25873.2.2.3 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
+
+objectclass ( 1.3.6.1.4.1.25873.2.2.1 NAME 'bitlBeeIMAccount' SUP account STRUCTURAL
+ DESC 'BitlBee IM Account '
+ MUST ( bitlBeeAccountNo, userid, userPassword )
+ MAY ( host, bitlBeeAutoconnect ) )
+
+objectclass ( 1.3.6.1.4.1.25873.2.2.2 NAME 'bitlBeeSetting' SUP top STRUCTURAL
+ DESC 'BitlBee Configuration Setting'
+ MUST ( bitlBeeSettingName )
+ MAY ( bitlBeeSettingValue ) )
+
+objectclass ( 1.3.6.1.4.1.25873.2.2.3 NAME 'bitlBeeBuddy' SUP top STRUCTURAL
+ DESC 'BitlBee Nick Mapping'
+ MUST ( bitlBeeBuddyHandle )
+ MAY ( ircNick ) )
diff --git a/irc.c b/irc.c
index 97365f4d..45a1940d 100644
--- a/irc.c
+++ b/irc.c
@@ -904,9 +904,31 @@ void irc_kick( irc_t *irc, user_t *u, char *channel, user_t *kicker )
void irc_kill( irc_t *irc, user_t *u )
{
- char *nick;
+ char *nick, *s;
+ char reason[64];
+
+ if( u->gc && u->gc->flags & OPT_LOGGING_OUT )
+ {
+ if( u->gc->user->proto_opt[0][0] )
+ g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost,
+ u->gc->user->proto_opt[0] );
+ else if( ( s = strchr( u->gc->username, '@' ) ) )
+ g_snprintf( reason, sizeof( reason ), "%s %s", irc->myhost,
+ s + 1 );
+ else
+ g_snprintf( reason, sizeof( reason ), "%s %s.%s", irc->myhost,
+ u->gc->prpl->name, irc->myhost );
+
+ /* proto_opt might contain garbage after the : */
+ if( ( s = strchr( reason, ':' ) ) )
+ *s = 0;
+ }
+ else
+ {
+ strcpy( reason, "Leaving..." );
+ }
- irc_write( irc, ":%s!%s@%s QUIT :%s", u->nick, u->user, u->host, "Leaving..." );
+ irc_write( irc, ":%s!%s@%s QUIT :%s", u->nick, u->user, u->host, reason );
nick = g_strdup( u->nick );
nick_lc( nick );
diff --git a/protocols/nogaim.c b/protocols/nogaim.c
index b1975f19..d4ccc3f1 100644
--- a/protocols/nogaim.c
+++ b/protocols/nogaim.c
@@ -293,7 +293,8 @@ void signoff( struct gaim_connection *gc )
account_t *a;
serv_got_crap( gc, "Signing off.." );
-
+ gc->flags |= OPT_LOGGING_OUT;
+
b_event_remove( gc->keepalive );
gc->keepalive = 0;
gc->prpl->close( gc );
diff --git a/protocols/nogaim.h b/protocols/nogaim.h
index b0319d27..2080465c 100644
--- a/protocols/nogaim.h
+++ b/protocols/nogaim.h
@@ -53,10 +53,12 @@
#define WEBSITE "http://www.bitlbee.org/"
#define IM_FLAG_AWAY 0x0020
-#define OPT_CONN_HTML 0x00000001
-#define OPT_LOGGED_IN 0x00010000
#define GAIM_AWAY_CUSTOM "Custom"
+#define OPT_CONN_HTML 0x00000001
+#define OPT_LOGGED_IN 0x00010000
+#define OPT_LOGGING_OUT 0x00020000
+
/* ok. now the fun begins. first we create a connection structure */
struct gaim_connection
{
diff --git a/storage.c b/storage.c
index b766c9e3..7a242c3c 100644
--- a/storage.c
+++ b/storage.c
@@ -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
+};