diff options
| author | Wilmer van der Gaast <wilmer@gaast.net> | 2006-06-07 15:36:19 +0200 | 
|---|---|---|
| committer | Wilmer van der Gaast <wilmer@gaast.net> | 2006-06-07 15:36:19 +0200 | 
| commit | 85e9644fe03cef7b83f3b3200943364e4eecaf14 (patch) | |
| tree | 1043b458bbcaac400c19a503aec13eb465ea4f65 | |
| parent | a312b6bcbc6aa836850d94fc2abc70ceffe275cd (diff) | |
| parent | 0025b5148725e524dfdc1da57b18fcd2be2608ee (diff) | |
Merging Jelmer's storage tree (with LDAP support).
| -rw-r--r-- | Makefile | 2 | ||||
| -rwxr-xr-x | configure | 46 | ||||
| -rw-r--r-- | doc/bitlbee.schema | 62 | ||||
| -rw-r--r-- | irc.c | 26 | ||||
| -rw-r--r-- | protocols/nogaim.c | 3 | ||||
| -rw-r--r-- | protocols/nogaim.h | 6 | ||||
| -rw-r--r-- | storage.c | 2 | ||||
| -rw-r--r-- | storage_ldap.c | 177 | 
8 files changed, 316 insertions, 8 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 @@ -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 ) ) @@ -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  { @@ -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 +}; | 
