[ejabberd] ejabberd starts external auth script but doesn't use it to auth users

Coiby Xu coiby.xu at gmail.com
Mon Apr 23 10:50:58 MSK 2012


Hi all,

I met a weird problem(My post at forum is not approved. So I resend this
question to this mailing list): ejabberd already starts external auth
script but doesn't use it to auth users.

Here are my configs(key part) and auth script:

1. in /etc/ejabberd/ejabberd.cfg
%%{auth_method, internal}.
%%
%% Store the plain passwords or hashed for SCRAM:
%%{auth_password_format, plain}.
%%{auth_password_format, scram}.

%%
%% Authentication using external script
%% Make sure the script is executable by ejabberd.
%%
{auth_method, external}.
{extauth_program, "/usr/share/gforge/src/plugins/ejabberd/auth/
gforge-auth.pl"}.
%%{extauth_cache, 600}.
%%{extauth_instances, 3}.

2. in /usr/share/gforge/src/plugins/ejabberd/auth/gforge-auth.pl
 #!/usr/bin/perl

# Postgresql-gforge external auth script
# Features: auth works. isUser works, and setPass works, with MD5
encryption.
# Restrictions: Username or passwords may not contain some special
characters: $'"` nor line breaks

# Security considerations:
#  - character filtering may not be perfect, but the most important '$"`
are filtered out by this script

# CHANGELOG:
#
# Based on check_postgresql.pl
# which can be found here:
http://www.ejabberd.im/files/efiles/check_postgresql.pl.txt

my $dbUser="gforge";  # The username to connect to postgresql
my $dbName="gforge"; # The name of the database inside postgresql
my $dbTable="users"; # The name of the table inside the database
my $fieldUser="user_name";   # The name of the field that holds jabber user
names
my $fieldPass="user_pw";   # The name of the field that holds jabber
passwords
my $fieldUnixPass="unix_pw";

use Unix::Syslog qw(:macros :subs);
use Digest::MD5 "md5_hex";
use Crypt::PasswdMD5 "unix_md5_crypt";

sub gensalt
{
    my @salt = ( '.', '/', 0 .. 9, 'A' .. 'Z', 'a' .. 'z' );
    my $salt;
    $salt .= (@salt)[rand @salt];
    $salt .= (@salt)[rand @salt];
    return $salt;
}

while(1)
  {

    my $buf = "";
    syslog LOG_INFO,"waiting for packet, hello";
    my $nread = sysread STDIN,$buf,2;
    do { syslog LOG_INFO,"port closed"; exit; } unless $nread == 2;
    my $len = unpack "n",$buf;
    my $nread = sysread STDIN,$buf,$len;

    my ($op,$user,$domain,$password) = split /:/,$buf;

    # Filter dangerous characters
    $user =~ s/[."\n\r'\$`]//g;
    $password =~ s/[."\n\r'\$`]//g;

    $unix_password = unix_md5_crypt( $password, gensalt() );
    $password = md5_hex($password);

    #$user =~ s/\./\//og;
    #my $jid = "$user\@$domain";
    my $result;
    syslog LOG_INFO,"nice, very nice";
    syslog(LOG_INFO,"request (%s)", $op);
    syslog(LOG_INFO,"buffer (%s)", $buf);
  SWITCH:
      {
$op eq 'auth' and do
  {
        $orden = "psql -U $dbUser $dbName --command \"select count(*) from
$dbTable where $fieldUser='$user' and $fieldPass='$password';\" |
grep '^ *[1-9][0-9]* *\$' &> /dev/null";
     syslog(LOG_INFO,"Executing: %s",$orden);

     # if command returned 0 we return 1
     $result = !system($orden);
  },last SWITCH;

$op eq 'setpass' and do
  {
            $unix_password =~ s/\$/\\\$/g;
            $orden = "psql -U $dbUser $dbName --command \"UPDATE $dbTable
SET $fieldPass='$password', $fieldUnixPass='$unix_password' where
$fieldUser='$user';\" | grep '^.*[1-9][0-9]* *\$' &> /dev/null";
            syslog(LOG_INFO,"Executing: %s",$orden);

            # if command returned 0 we return 1
            $result = !system($orden);

  },last SWITCH;

        $op eq 'isuser' and do
          {
             # password is null. Return 1 if the user $user exists.
     $result = 0;
             $orden = "psql -U $dbUser $dbName --command \"select count(*)
from $dbTable where $fieldUser='$user';\" | grep '^ *[1-9][0-9]* *\$' &>
/dev/null";
     syslog(LOG_INFO,"auth: Executing is_user: %s",$orden);

     # if command returned 0 we return 1
     $result = !system($orden);
          },last SWITCH;
      };
    my $out = pack "nn",2,$result ? 1 : 0;
    syswrite STDOUT,$out;
  }

closelog;

In /var/log/message, there are logs and we only have these:

Apr 23 10:41:45 innov perl: waiting for packet, hello

and /var/log/ejabberd/ejabber.log

I(<0.500.0>:ejabberd_c2s:775) :
({socket_state,gen_tcp,#Port<0.3374>,<0.499.0>}) Accepted authentication
for coibyt by ejabberd_auth_internal
...
I(<0.485.0>:ejabberd_c2s:810) :
({socket_state,gen_tcp,#Port<0.3351>,<0.484.0>}) Failed authentication for
coibyt at innov.zjustu.org

According to the logs, ejabberd is starting the auth script but doesn't use
that script to auth user, why?

Btw, who's the user that runs the external auth script?

Thanks!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.jabber.ru/pipermail/ejabberd/attachments/20120423/4e613d97/attachment.html>


More information about the ejabberd mailing list