Index: Makefile.in =================================================================== --- Makefile.in (revisión: 650) +++ Makefile.in (copia de trabajo) @@ -27,7 +27,7 @@ prefix = @prefix@ -SUBDIRS = @mod_irc@ @mod_pubsub@ @mod_muc@ @eldap@ @web@ stringprep @tls@ @odbc@ @ejabberd_zlib@ +SUBDIRS = @mod_irc@ @mod_pubsub@ @mod_muc@ @eldap@ @web@ stringprep @tls@ @odbc@ @ejabberd_zlib@ @sasl@ ERLSHLIBS = expat_erl.so SOURCES = $(wildcard *.erl) BEAMS = $(SOURCES:.erl=.beam) Index: ejabberd.cfg.example =================================================================== --- ejabberd.cfg.example (revisión: 650) +++ ejabberd.cfg.example (copia de trabajo) @@ -95,7 +95,10 @@ %{auth_method, odbc}. %{odbc_server, "DSN=ejabberd;UID=ejabberd;PWD=ejabberd"}. +% If you want to allow SASL authentication: +{auth_method, [sasl]}. + % Host name: {hosts, ["localhost"]}. Index: configure.ac =================================================================== --- configure.ac (revisión: 650) +++ configure.ac (copia de trabajo) @@ -16,6 +16,10 @@ AM_WITH_EXPAT #locating zlib AM_WITH_ZLIB +#locating zlib +AM_WITH_ZLIB +# for SASL +AM_WITH_SASL # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -27,6 +31,7 @@ AC_FUNC_MALLOC AC_HEADER_STDC +AC_MOD_ENABLE(sasl, yes) AC_MOD_ENABLE(mod_pubsub, yes) AC_MOD_ENABLE(mod_irc, yes) AC_MOD_ENABLE(mod_muc, yes) @@ -55,6 +60,7 @@ AC_SUBST(db_type) AC_CONFIG_FILES([Makefile + $make_sasl $make_mod_irc $make_mod_muc $make_mod_pubsub Index: sasl/ejabberd_auth_sasl.c =================================================================== --- sasl/ejabberd_auth_sasl.c (revisión: 0) +++ sasl/ejabberd_auth_sasl.c (revisión: 0) @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include + +typedef struct +{ + ErlDrvPort port; + + /* The SASL context kept for the life of the connection */ + sasl_conn_t *conn; + +} ejabberd_sasl_data; + +void sasl_start(ejabberd_sasl_data* data) +{ + int result; + + /* Initialize SASL */ + result=sasl_server_init(NULL, /* Callbacks supported */ + "TestServer"); /* Name of the application */ + + /* Make a new context for this connection */ + result=sasl_server_new("ejabberd_auth_sasl", /* Registered name of service */ + NULL, /* my fully qualified domain name; + NULL says use gethostname() */ + NULL, /* The user realm used for password + lookups; NULL means default to serverFQDN + Note: This does not affect Kerberos */ + NULL, NULL, /* IP Address information strings */ + NULL, /* Callbacks supported only for this connection */ + 0, /* security flags (security layers are enabled + * using security properties, separately)*/ + &data->conn); +} + +int login(ejabberd_sasl_data* data,const char* user,const char* pass) +{ + int result; + const char *out; + + //printf("login %s %s\r\n",user,pass); + + result=sasl_checkpass(data->conn,user,strlen(user),pass,strlen(pass)); + + //printf("%s\r\n",sasl_errstring(result,NULL,NULL)); + + if(result==SASL_OK) + return 1; + + return 0; +} + +int exist(ejabberd_sasl_data* data,const char* user) +{ + int result; + const char *out; + + //printf("exist %s\r\n",user); + + result=sasl_user_exists(data->conn,"ejabberd_auth_sasl",NULL,user); + + //printf("%s\r\n",sasl_errstring(result,NULL,NULL)); + + if(result!=SASL_NOUSER) + return 1; + + return 0; +} + +void sasl_stop(ejabberd_sasl_data* data) +{ + int result; + + sasl_dispose(&data->conn); + sasl_done(); +} + +#define DECODE_STRING(buffer, index, result) \ + { \ + int tmp = 0; int size = 0; \ + ei_get_type(buffer, index, &tmp, &size); \ + result = malloc(size + 1); \ + ei_decode_string(buffer, index, result); \ + } + +#define RETURN_INT(value) \ + { \ + ErlDrvBinary* b = driver_alloc_binary(1); \ + rlen = 1; \ + b->orig_bytes[0] = value; \ + *rbuf = (char*)b; \ + return rlen; \ + } + +static ErlDrvData start( ErlDrvPort port, char* command ) +{ + printf( "SASL-AUTH driver start\r\n" ); + + ejabberd_sasl_data *d = (ejabberd_sasl_data *)driver_alloc( sizeof( ejabberd_sasl_data )); + d->port = port; + set_port_control_flags( port, PORT_CONTROL_FLAG_BINARY ); + + sasl_start(d); + + return (ErlDrvData)d; +}; + +static void stop( ErlDrvData handle ) { + sasl_stop(handle); + + driver_free( (char *)handle ); + + printf( "SASL-AUTH driver stop\r\n" ); +}; + +static int er_login(ErlDrvData drv_data, char* buf) +{ + int iSize = 0; + int iIndex = 0; + int iResult = 0; + // Parse the version and tuple header + ei_decode_version( buf, &iIndex, &iSize ); + ei_decode_tuple_header( buf, &iIndex, &iSize ); + if ( iSize == 2 ) + { + const char* user; + const char* pass; + // The first item in the tuple should be the username + DECODE_STRING( buf, &iIndex, user ); + DECODE_STRING( buf, &iIndex, pass ); + if(login(drv_data,user,pass)) + return 1; + }else if(iSize==1) + { + const char* user; + DECODE_STRING( buf, &iIndex, user ); + if(exist(drv_data,user)) + return 1; + }else + { + ;// wrong args + } + return 0; +}; + +static int control( ErlDrvData drv_data, unsigned int command, char *buf, int len, char** rbuf, int rlen ) +{ + int iResult; + iResult=er_login(drv_data, buf ); + RETURN_INT( iResult ); +}; + +static ErlDrvEntry entry = +{ + NULL, /* F_PTR init, N/A */ + start, /* L_PTR start, called when port is opened */ + stop, /* F_PTR stop, called when port is closed */ + NULL, /* F_PTR output, called when erlang has sent */ + NULL, /* F_PTR ready_input, called when input descriptor ready */ + NULL, /* F_PTR ready_output, called when output descriptor ready */ + "ejabberd_auth_sasl", /* char *driver_name, the argument to open_port */ + NULL, /* F_PTR finish, called when unloaded */ + NULL, /* handle */ + control, /* F_PTR control, port_command callback */ + NULL, /* F_PTR timeout, reserved */ + NULL /* F_PTR outputv, reserved */ +}; + +DRIVER_INIT(ejabberd_auth_sasl) /* must match name in driver_entry */ +{ + return &entry; +}; + Index: sasl/ejabberd_auth_sasl.erl =================================================================== --- sasl/ejabberd_auth_sasl.erl (revisión: 0) +++ sasl/ejabberd_auth_sasl.erl (revisión: 0) @@ -0,0 +1,70 @@ +-module(ejabberd_auth_sasl). +-author(''). + +-export([ + start/1, + plain_password_required/0, + set_password/3, + try_register/3, + remove_user/2, + remove_user/3, + get_password/2, + get_password_s/2, + is_user_exists/2, + get_vh_registered_users/1, + check_password/3, + check_password/5 + ]). + +start( _Host ) -> + case erl_ddll:load_driver( ejabberd:get_so_path(), ejabberd_auth_sasl) of + ok -> ok; + {error, already_loaded} -> ok; + Error -> exit({error, could_not_load_driver, Error}) + end. + +plain_password_required() -> + true. + +check_password( User, Server, Password ) -> + Port = open_port( { spawn, ejabberd_auth_sasl }, [ binary ] ), + Bin = term_to_binary( { User, Password }), + Res = port_control( Port, 0, Bin ), + case Res of + <<1>> -> true; + _ -> false + end. + +check_password( User, Server, Password, _StreamID, _Digest ) -> + check_password( User, Server, Password ). + +set_password( _User, _Server, _Password ) -> + { error, not_allowed }. + +try_register( _User, _Server, _Password ) -> + { error, not_allowed }. + +remove_user( _User, _Server ) -> + { error, not_allowed }. + +remove_user( _User, _Server, _Password ) -> + { error, not_allowed }. + +get_vh_registered_users( _Server ) -> + []. + +is_user_exists( _User, _Server ) -> + Port = open_port( { spawn, ejabberd_auth_sasl }, [ binary ] ), + Bin = term_to_binary( { _User }), + Res = port_control( Port, 0, Bin ), + case Res of + <<1>> -> true; + _ -> false + end. + +get_password( _User, _Server ) -> + false. + +get_password_s( _User, _Server ) -> + "". + Index: sasl/Makefile.in =================================================================== --- sasl/Makefile.in (revisión: 0) +++ sasl/Makefile.in (revisión: 0) @@ -0,0 +1,35 @@ +# $Id: Makefile.in 285 2006-12-11 10:16:21Z $ + +CC = @CC@ +CFLAGS = @CFLAGS@ @SASL_CFLAGS@ @ERLANG_CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ @SASL_LIBS@ @ERLANG_LIBS@ + +SUBDIRS = + +ERLSHLIBS = ../ejabberd_auth_sasl.so + +OUTDIR = .. +EFLAGS = -I .. -pz .. +OBJS = \ + $(OUTDIR)/ejabberd_auth_sasl.beam + +all: $(OBJS) $(ERLSHLIBS) + +$(OUTDIR)/%.beam: %.erl + @ERLC@ -W $(EFLAGS) -o $(OUTDIR) $< + +$(ERLSHLIBS): ../%.so: %.c + $(CC) -Wall $(CFLAGS) $(LDFLAGS) \ + $(subst ../,,$(subst .so,.c,$@)) $(LIBS) \ + -o $@ -fpic -shared + +clean: + rm -f $(OBJS) $(ERLSHLIBS) + +distclean: clean + rm -f Makefile + +TAGS: + etags *.erl[/quote] Index: aclocal.m4 =================================================================== --- aclocal.m4 (revisión: 650) +++ aclocal.m4 (copia de trabajo) @@ -292,3 +292,36 @@ fi ]) dnl + +AC_DEFUN(AM_WITH_SASL, +[ AC_ARG_WITH(sasl2, [ --with-sasl=PREFIX prefix where SASL is installed ]) +unset SASL_LIBS; +unset SASL_CFLAGS; + +if test x"$with_sasl" != x; then + SASL_CFLAGS="-I$with_sasl/include" + SASL_LIBS="-L$with_sasl/lib" +fi + +AC_CHECK_LIB(sasl2, sasl_server_init, + [ SASL_LIBS="$SASL_LIBS -lsasl2" sasl_found=yes ], + [ sasl_found=no ], + "$SASL_LIBS") + +if test $sasl_found = no; then + AC_MSG_ERROR([Could not find sasl/sasl.h]) +fi + +if test $sasl_found = yes; then + sasl_save_CFLAGS="$CFLAGS" + CFLAGS="$SASL_CFLAGS $CFLAGS" + AC_CHECK_HEADERS(sasl/sasl.h, ,$sasl_found=no) + if test $sasl_found = no; then + AC_MSG_ERROR([Could not find sasl/sasl.h]) + fi + CFLAGS=$sasl_save_CFLAGS + + AC_SUBST(SASL_CFLAGS) + AC_SUBST(SASL_LIBS) +fi +])