#!/usr/bin/perl # Postgresql external auth script # Features: auth works. isUser should work, but setPass doesn't. # Restrictions: Username or passwords may not contain some special characters: $'"` nor line breaks # Security considerations: # - i am not sure whether password is shown in the "echo" sentence when listing processes, perhaps not if echo is a shell builtin # - character filtering may not be perfect, but the most important '$"` are filtered out by this script # - psql user password must be set in ~/.pgpass which is of the format: # localhost:port:database:user:password # # CHANGELOG: # # 2005-12-27 Modified by Adam Thorsen http://www.guruza.com/oss # Based on Alejandro Grijalba's ejabberd_mysql_auth.pl script # which can be found here: http://www.latinsud.com/ejabberd_mysql_auth.pl # # 2007-11-21 Modified by Badlop and Sps_black to make compatible with recent ejabberd SVN. my $dbUser="web"; # The username to connect to postgresql my $dbName="guruza_dev"; # The name of the database inside postgresql my $dbTable="users"; # The name of the table inside the database my $fieldUser="handle"; # The name of the field that holds jabber user names my $fieldPass="password"; # The name of the field that holds jabber passwords use Unix::Syslog qw(:macros :subs); # my $domain = $ARGV[0] || "guruza.com"; while(1) { # my $rin = '',$rout; # vec($rin,fileno(STDIN),1) = 1; # $ein = $rin; # my $nfound = select($rout=$rin,undef,undef,undef); my $buf = ""; syslog LOG_INFO,"waiting for packet"; 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; #$user =~ s/\./\//og; my $jid = "$user\@$domain"; my $result; 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='$jid' 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 { $result = 0; },last SWITCH; $op eq 'isuser' and do { # password is null. Return 1 if the user $user\@$domain exists. $result = 0; $orden = "psql -U $dbUser $dbName --command \"select count(*) from $dbTable where $fieldUser='$jid';\" | 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;