SOURCES: ejabberd-auth_pam.patch (NEW) - New file: PAM authenticat...
japhy
japhy at pld-linux.org
Tue Feb 13 08:56:48 CET 2007
Author: japhy Date: Tue Feb 13 07:56:48 2007 GMT
Module: SOURCES Tag: HEAD
---- Log message:
- New file: PAM authentication support for ejabberd.
---- Files affected:
SOURCES:
ejabberd-auth_pam.patch (NONE -> 1.1) (NEW)
---- Diffs:
================================================================
Index: SOURCES/ejabberd-auth_pam.patch
diff -u /dev/null SOURCES/ejabberd-auth_pam.patch:1.1
--- /dev/null Tue Feb 13 08:56:48 2007
+++ SOURCES/ejabberd-auth_pam.patch Tue Feb 13 08:56:43 2007
@@ -0,0 +1,497 @@
+Source: http://ejabberd.jabber.ru/files/contributions/ejabberd_auth_pam.diff
+
+Index: Makefile.in
+===================================================================
+--- Makefile.in (revisión: 705)
++++ 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@ @pam@
+ ERLSHLIBS = expat_erl.so
+ SOURCES = $(wildcard *.erl)
+ BEAMS = $(SOURCES:.erl=.beam)
+Index: ejabberd.cfg.example
+===================================================================
+--- ejabberd.cfg.example (revisión: 705)
++++ ejabberd.cfg.example (copia de trabajo)
+@@ -95,7 +95,14 @@
+ %{auth_method, odbc}.
+ %{odbc_server, "DSN=ejabberd;UID=ejabberd;PWD=ejabberd"}.
+
++% If you want to allow both internal and PAM authentication:
++{auth_method, [internal, pam]}.
++% Default PAM service "login" can be changed with:
++%{pam_service, "login"}.
++% Default PAM prompt "Password:" can be changed with:
++%{pam_prompt_pwd, "Password:"}.
+
++
+ % Host name:
+ {hosts, ["localhost"]}.
+
+Index: configure.ac
+===================================================================
+--- configure.ac (revisión: 705)
++++ configure.ac (copia de trabajo)
+@@ -16,6 +16,10 @@
+ AM_WITH_EXPAT
+ #locating zlib
+ AM_WITH_ZLIB
++#locating zlib
++AM_WITH_ZLIB
++#locating Linux-PAM
++AM_WITH_PAM
+
+ # Checks for typedefs, structures, and compiler characteristics.
+ AC_C_CONST
+@@ -27,6 +31,7 @@
+ AC_FUNC_MALLOC
+ AC_HEADER_STDC
+
++AC_MOD_ENABLE(pam, 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_pam
+ $make_mod_irc
+ $make_mod_muc
+ $make_mod_pubsub
+Index: pam/Makefile.in
+===================================================================
+--- pam/Makefile.in (revisión: 0)
++++ pam/Makefile.in (revisión: 0)
+@@ -0,0 +1,35 @@
++# $Id$
++
++CC = @CC@
++CFLAGS = @CFLAGS@ @PAM_CFLAGS@ @ERLANG_CFLAGS@
++CPPFLAGS = @CPPFLAGS@
++LDFLAGS = @LDFLAGS@
++LIBS = @LIBS@ @PAM_LIBS@ @ERLANG_LIBS@
++
++SUBDIRS =
++
++ERLSHLIBS = ../ejabberd_auth_pam.so
++
++OUTDIR = ..
++EFLAGS = -I .. -pz ..
++OBJS = \
++ $(OUTDIR)/ejabberd_auth_pam.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
+Index: pam/ejabberd_auth_pam.c
+===================================================================
+--- pam/ejabberd_auth_pam.c (revisión: 0)
++++ pam/ejabberd_auth_pam.c (revisión: 0)
+@@ -0,0 +1,255 @@
++#include <stdio.h>
++#include <string.h>
++#include <ei.h>
++#include <erl_driver.h>
++#include <security/pam_appl.h>
++
++#ifdef LINUX_PAM /* XXX: and OpenPAM? */
++# define PAM_MSG_MEMBER(msg, n, member) ((msg)[(n)]->member)
++#else
++# define PAM_MSG_MEMBER(msg, n, member) ((*(msg))[(n)].member)
++#endif
++
++//
++#ifndef LINKEDLIBPAM
++#include <dlfcn.h>
++
++#ifndef LIBPAMPATH
++#define LIBPAMPATH "/usr/lib/libpam.so"
++#endif
++
++static void *libpam_h = NULL;
++
++void init_libpam() {
++ if ( libpam_h == NULL ) {
++ libpam_h = dlopen( LIBPAMPATH, RTLD_GLOBAL | RTLD_NOW );
++ printf( "Open: %s\r\n", LIBPAMPATH );
++ };
++};
++
++void fin_libpam() {
++ if ( libpam_h != NULL ) {
++ dlclose( libpam_h );
++ libpam_h = NULL;
++ printf( "Close: %s\r\n", LIBPAMPATH );
++ };
++};
++#endif
++//
++
++typedef struct _PromptMatch {
++ struct _PromptMatch* next;
++ char* prompt;
++ char* response;
++} *PromptMatch;
++
++typedef struct {
++ ErlDrvPort port;
++} ejabberd_pam_data;
++
++static PromptMatch _newMatch( PromptMatch list, char* prompt, char* response ) {
++ PromptMatch result = ( PromptMatch)malloc( sizeof( struct _PromptMatch ));
++ bzero( result, sizeof( struct _PromptMatch ));
++ result->prompt = prompt;
++ result->response = response;
++ result->next = list;
++ return result;
++};
++
++static char* _findMatch( PromptMatch list, const char* prompt ) {
++ PromptMatch cur = list;
++ while ( cur != NULL ) {
++ if ( strstr( prompt, cur->prompt ) != 0 )
++ return cur->response;
++ cur = cur->next;
++ };
++ return NULL;
++};
++
++static void _cleanupMatch( PromptMatch list ) {
++ PromptMatch cur = list;
++ PromptMatch next;
++ while ( cur != NULL ) {
++ next = cur->next;
++ free( cur->prompt );
++ free( cur->response );
++ free( cur );
++ cur = next;
++ };
++};
++
++static int pam_conversation( int msgcnt, const struct pam_message** msgs, struct pam_response** res, void* arg ) {
++ int iResult = PAM_CONV_ERR;
++ if (( msgcnt > 0 ) || ( msgcnt <= PAM_MAX_NUM_MSG )) {
++ // Allocate a response for each message
++ int iSizeResponse = sizeof( struct pam_response ) * msgcnt;
++ struct pam_response *reply = (struct pam_response *)malloc( iSizeResponse );
++ if ( reply != NULL ) {
++ bzero( reply, iSizeResponse );
++ // Walk each message from PAM and lookup the response corresponding to each prompt
++ int ii;
++ char* response;
++ for ( ii = 0; ii < msgcnt; ii++ ) {
++ printf( "prompt(index %d)(style %d): %s\r\n", ii, PAM_MSG_MEMBER( msgs, ii, msg_style ), PAM_MSG_MEMBER( msgs, ii, msg ));
++ switch ( PAM_MSG_MEMBER( msgs, ii, msg_style )) {
++ case PAM_PROMPT_ECHO_ON :
++ case PAM_PROMPT_ECHO_OFF :
++ // Find the response for the current prompt; if none is found, warn
++ response = _findMatch( (PromptMatch)arg, PAM_MSG_MEMBER( msgs, ii, msg ));
++ if ( response != NULL ) {
++ // Copy password into response
++ reply[ ii ].resp = strdup( response );
++ reply[ ii ].resp_retcode = PAM_SUCCESS;
++ } else {
++ printf("Warning: No prompt found for: %s\r\n", PAM_MSG_MEMBER( msgs, ii, msg ));
++ reply[ ii ].resp = strdup( "Unexpected prompt" );
++ reply[ ii ].resp_retcode = PAM_SUCCESS;
++ };
++ break;
++ default :
++ reply[ ii ].resp = strdup("");
++ reply[ ii ].resp_retcode = PAM_SUCCESS;
++ };
++ };
++ *res = reply;
++ iResult = PAM_SUCCESS;
++ };
++ };
++ return iResult;
++};
++
++#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( "PAM-AUTH driver start\r\n" );
++ #ifndef LINKEDLIBPAM
++ init_libpam();
++ #endif
++ ejabberd_pam_data *d = (ejabberd_pam_data *)driver_alloc( sizeof( ejabberd_pam_data ));
++ d->port = port;
++ set_port_control_flags( port, PORT_CONTROL_FLAG_BINARY );
++ return (ErlDrvData)d;
++};
++
++static void stop( ErlDrvData handle ) {
++ driver_free( (char *)handle );
++ #ifndef LINKEDLIBPAM
++ fin_libpam();
++ #endif
++ printf( "PAM-AUTH driver stop\r\n" );
++};
++
++static int auth_params( char* buf, PromptMatch* head ) {
++ int iSize = 0;
++ int iIndex = 0;
++ int iResult = 0;
++ char* prompt = NULL;
++ char* response = NULL;
++ // Parse the version and tuple header
++ ei_decode_version( buf, &iIndex, &iSize );
++ ei_decode_tuple_header( buf, &iIndex, &iSize );
++ if ( iSize == 2 ) {
++ // The first item in the tuple should be the username
++ DECODE_STRING( buf, &iIndex, response );
++ *head = _newMatch( *head, strdup( "login" ), response );
++
++ // The second item in the tuple should be a list of tuples
++ // Each tuple in the list consists of the expected prompt string
++ // and the value to return at that prompt
++ ei_decode_list_header( buf, &iIndex, &iSize );
++
++ // Loop over the list and pull out each prompt/response tuple and
++ // store it into a PromptItem list that will get processed in
++ // the PAM conversation
++ int ii = 0;
++ for ( ii = 0; ii < iSize; ii++ ) {
++ int iTupleSize = 0;
++ ei_decode_tuple_header( buf, &iIndex, &iTupleSize );
++ if ( iTupleSize != 2 ) {
++ printf( "Incorrect number of arguments in prompt/response tuple(index %d): %d\r\n", ii, iTupleSize );
++ } else {
++ // Decode the prompt from the tuple
++ DECODE_STRING( buf, &iIndex, prompt );
++ DECODE_STRING( buf, &iIndex, response );
++ // Add a new prompt item to track this prompt/response pair
++ *head = _newMatch( *head, prompt, response );
++ };
++ };
++ iResult = 1;
++ };
++ return iResult;
++};
++
++static int auth( PromptMatch head ) {
++ // Setup PAM conversation structure; pass in the prompt match list
++ // so we can process the prompts from PAM
++ int flags = 0; //PAM_SILENT
++ int iResult = 0;
++ pam_handle_t* pam = NULL;
++
++ char* service = _findMatch( head, "service" );
++ char* username = _findMatch( head, "login" );
++
++ struct pam_conv conv = { pam_conversation, head };
++
++ // Spin up PAM
++ int rc = pam_start( service, username, &conv, &pam );
++ if ( rc == PAM_SUCCESS ) {
++ // Attempt to authenticate the user
++ rc = pam_authenticate( pam, flags );
++ if ( rc != PAM_SUCCESS )
++ printf("Authentication failed for: %s. Error: %s\r\n", username, pam_strerror( NULL, rc ));
++ else
++ iResult = 1;
++ pam_end( pam, rc );
++ } else
++ printf("Unable to spin up PAM: %s\r\n", pam_strerror( NULL, rc ));
++ return iResult;
++};
++
++static int control( ErlDrvData drv_data, unsigned int command, char *buf,
++ int len, char** rbuf, int rlen ) {
++ int iResult;
++ PromptMatch head = NULL;
++ if (( iResult = auth_params( buf, &head )) != 0 ) {
++ iResult = auth( head );
++ _cleanupMatch( head );
++ };
++ RETURN_INT( iResult );
++};
++
++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_pam", /* 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_pam) /* must match name in driver_entry */
++{
++ return &entry;
++};
+Index: pam/ejabberd_auth_pam.erl
+===================================================================
+--- pam/ejabberd_auth_pam.erl (revisión: 0)
++++ pam/ejabberd_auth_pam.erl (revisión: 0)
+@@ -0,0 +1,90 @@
++-module(ejabberd_auth_pam).
++-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_pam) 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 ) ->
++ PAMService =
++ case ejabberd_config:get_local_option( { pam_service, Server } ) of
++ undefined ->
++ "login";
++ Service ->
++ Service
++ end,
++ PAMPrompt =
++ case ejabberd_config:get_local_option( { pam_prompt_pwd, Server } ) of
++ undefined ->
++ "Password:";
++ Prompt ->
++ Prompt
++ end,
++ Port = open_port( { spawn, ejabberd_auth_pam }, [ binary ] ),
++ Bin = term_to_binary( { User, [ { PAMPrompt, Password }, { "service", PAMService } ] }),
++ Res = port_control( Port, 1, Bin ),
++ case Res of
++ <<0>> -> false;
++ <<1>> -> true;
++ _ -> undefined
++ 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 ) ->
++ {ok,FileBin}=file:read_file("/etc/passwd"),
++ Tmp=binary_to_list(FileBin),
++ FileStr=string:concat("\n", Tmp),
++
++ Tmp2=string:concat("\n", _User),
++ RegExp=string:concat(Tmp2, ":"),
++
++ case regexp:match(FileStr, RegExp) of
++ {match, _, _} ->
++ true;
++ _ ->
++ false
++ end.
++
++get_password( _User, _Server ) ->
++ false.
++
++get_password_s( _User, _Server ) ->
++ "".
+Index: aclocal.m4
+===================================================================
+--- aclocal.m4 (revisión: 705)
++++ aclocal.m4 (copia de trabajo)
+@@ -292,3 +292,32 @@
+ fi
+ ])
+ dnl <openssl/>
++
++AC_DEFUN(AM_WITH_PAM,
++[ AC_ARG_WITH(pam, [ --with-pam=PREFIX prefix where PAM is installed ])
++unset PAM_LIBS;
++unset PAM_CFLAGS;
++
++if test x"$with_pam" != x; then
++ PAM_CFLAGS="-I$with_pam/include"
++ PAM_LIBS="-L$with_pam/lib"
++fi
++
++AC_CHECK_LIB(pam, pam_start,
++ [ PAM_LIBS="$PAM_LIBS -lpam" pam_found=yes ],
++ [ pam_found=no ],
++ "$PAM_LIBS")
++
++if test $pam_found = yes; then
++ pam_save_CFLAGS="$CFLAGS"
++ CFLAGS="$PAM_CFLAGS $CFLAGS"
++ AC_CHECK_HEADERS(security/pam_appl.h, ,$pam_found=no)
++ if test $pam_found = no; then
++ AC_MSG_ERROR([Could not find security/pam_appl.h])
++ fi
++ CFLAGS=$pam_save_CFLAGS
++
++ AC_SUBST(PAM_CFLAGS)
++ AC_SUBST(PAM_LIBS)
++fi
++])
================================================================
More information about the pld-cvs-commit
mailing list