Asterisk authenticate using voicemail passwords

I got full of having to tell users that we couldn't use their voicemail password in other
application, so I wrote this simple AGI script that parses voicemail.conf contents and
checks for a match against provided extension and password. It returns 0 on
success or 1 on failure.

Hope it help others to integrate application passwords.


chk_vm_pwd.agi



#!/usr/bin/perl

  1. AGI script that searchs for a match on an extension and password in
  2. a voicemail.conf file
  3. Parameters: <voicemail config file path> | <extension> | <password>
  4. Written by: Andre D. Correa <andre(at)pobox.com> (03/jun/2005)

  1. Added by Suretec Systems Ltd - 10/06/2006
use strict;
use warnings;

use Asterisk::AGI;
$AGI = new Asterisk::AGI;
my %input = $AGI->ReadParse();

  1. Set variables according to supplied arquments
  2. Variables sanitation is not an issue as it is being run from extentions.conf
$vmconf = $ARGV[0];
$exten = $ARGV[1];
$pwd = $ARGV[2];

  1. Open VoiceMail configuration file read only
open VMCONF, "<$vmconf";
@vmconf_lines = <VMCONF>;
close VMCONF;
&error_msg("Cannot open $vmconf file read only.") if $#vmconf_lines eq -1;

foreach (@vmconf_lines){
next if $_ !~ /^\d/;
$_ =~ s/\s//iog;
$_ =~ s/=>/=/iog;
$_ =~ s/=/\,/;
(@line_args) = split(/\,/, $_);
if ($exten eq $line_args[0]){ # We got the right extension
if ($pwd eq $line_args[1]){ # User provided the right pwd
$AGI->set_variable('result','0');
} else { # Wrong password - bye!
$AGI->set_variable('result','1');
}
}
}

exit;


sub error_msg() {
my($err_msg) = @_;
$AGI->verbose($err_msg);
$AGI->hangup();
die $err_msg;
}



To use it I make sonething like this in my extensions.conf file:

exten => *122,1,Answer()
exten => *122,2,Read(ext_num,vm-extension)
exten => *122,3,Wait(1)
exten => *122,4,Read(ext_pwd,vm-password)
exten => *122,5,Wait(1)
exten => *122,6,agi,chk_vm_pwd.agi|/etc/asterisk/voicemail.conf|${ext_num}|${ext_pwd}
exten => *122,7,GotoIf($[["${result}" = "0"]?20:30)
exten => *122,20,Playback(agent-loginok)
exten => *122,21,Hangup()
exten => *122,30,PlayBack(invalid)
exten => *122,31,Hangup()

With this you can make all of your applications authenticate with the voicemail password. For sure a more robust authentication scheme is needed to Asterisk, meanwhile this will do the job.

I hope to make the script work looking on a MySQL database. I'll update this page if and when I have it done. Have fun!


Again, in PHP format

Another version, slightly simpler use written by Corey Frang. Uses PHP.


vm-pw.agi

#!/usr/bin/php -q
<?
ob_implicit_flush(false);
error_reporting(0);
set_time_limit(5);

$stdin = fopen('php://stdin', 'r');
$stdlog = fopen('/var/log/asterisk/agitest.log', 'a');
$debug = 0;

function read() {
global $stdin;
$input = str_replace("\n", "", fgets($stdin, 4096));
dlog("read: $input\n");
return $input;
}

function write($line) {
dlog("write: $line\n");
echo $line."\n";
}

function dlog($line) {
global $debug, $stdlog;
if ($debug) fputs($stdlog, $line);
}

// parse agi headers into array
while ($env=read()) {
$s = split(": ",$env);
$agi[str_replace("agi_","",$s0)] = trim($s1);
if $env == "") {
break;
}
}

$vmbox = $_SERVER["argv"][1];
$vmbox = trim($vmbox);
$parts = split("@",$vmbox);


$pwauth = 0;

$fp = fopen("/etc/asterisk/voicemail.conf","r");
while ($s = fgets($fp))
{
if ($s{0} == ";") continue;
$s = trim($s);
if (preg_match("/^\[(.*)\]/i", $s, $match))
{
if (strtolower($match[1]) == strtolower($parts[1]))
{
$right = 1; dlog($s."\n");
} else {
$right = 0;
}
}
if ($right && preg_match("/^(".$parts[0].")\s*\=\>\s*(\d*)/",$s,$match))
{
if (strtolower($match[1]) == strtolower($parts[0]))
{
$pwauth = $match[2]; dlog($pwauth."\n");
fclose($fp);
}
}
}

if ($pwauth) {
write("EXEC Authenticate $pwauth");
$result = read();
$resultcode = split("=", $result);
if ($resultcode[1] == -1)
{
write("Hangup");
read();
}
} else {
write("Hangup");
read();
}

// clean up file handlers etc.
fclose($in);
fclose($stdlog);
exit;

?>


extensions.conf - example

exten => 120,1,Answer()
exten => 120,2,AGI(vm-pw.agi,2205@pstn)
exten => 120,3,Playback(lots-o-monkeys)

The only argument to this AGI is the extension and voicemail context to use. It uses "Authenticate" to get the password.
I got full of having to tell users that we couldn't use their voicemail password in other
application, so I wrote this simple AGI script that parses voicemail.conf contents and
checks for a match against provided extension and password. It returns 0 on
success or 1 on failure.

Hope it help others to integrate application passwords.


chk_vm_pwd.agi



#!/usr/bin/perl

  1. AGI script that searchs for a match on an extension and password in
  2. a voicemail.conf file
  3. Parameters: <voicemail config file path> | <extension> | <password>
  4. Written by: Andre D. Correa <andre(at)pobox.com> (03/jun/2005)

  1. Added by Suretec Systems Ltd - 10/06/2006
use strict;
use warnings;

use Asterisk::AGI;
$AGI = new Asterisk::AGI;
my %input = $AGI->ReadParse();

  1. Set variables according to supplied arquments
  2. Variables sanitation is not an issue as it is being run from extentions.conf
$vmconf = $ARGV[0];
$exten = $ARGV[1];
$pwd = $ARGV[2];

  1. Open VoiceMail configuration file read only
open VMCONF, "<$vmconf";
@vmconf_lines = <VMCONF>;
close VMCONF;
&error_msg("Cannot open $vmconf file read only.") if $#vmconf_lines eq -1;

foreach (@vmconf_lines){
next if $_ !~ /^\d/;
$_ =~ s/\s//iog;
$_ =~ s/=>/=/iog;
$_ =~ s/=/\,/;
(@line_args) = split(/\,/, $_);
if ($exten eq $line_args[0]){ # We got the right extension
if ($pwd eq $line_args[1]){ # User provided the right pwd
$AGI->set_variable('result','0');
} else { # Wrong password - bye!
$AGI->set_variable('result','1');
}
}
}

exit;


sub error_msg() {
my($err_msg) = @_;
$AGI->verbose($err_msg);
$AGI->hangup();
die $err_msg;
}



To use it I make sonething like this in my extensions.conf file:

exten => *122,1,Answer()
exten => *122,2,Read(ext_num,vm-extension)
exten => *122,3,Wait(1)
exten => *122,4,Read(ext_pwd,vm-password)
exten => *122,5,Wait(1)
exten => *122,6,agi,chk_vm_pwd.agi|/etc/asterisk/voicemail.conf|${ext_num}|${ext_pwd}
exten => *122,7,GotoIf($[["${result}" = "0"]?20:30)
exten => *122,20,Playback(agent-loginok)
exten => *122,21,Hangup()
exten => *122,30,PlayBack(invalid)
exten => *122,31,Hangup()

With this you can make all of your applications authenticate with the voicemail password. For sure a more robust authentication scheme is needed to Asterisk, meanwhile this will do the job.

I hope to make the script work looking on a MySQL database. I'll update this page if and when I have it done. Have fun!


Again, in PHP format

Another version, slightly simpler use written by Corey Frang. Uses PHP.


vm-pw.agi

#!/usr/bin/php -q
<?
ob_implicit_flush(false);
error_reporting(0);
set_time_limit(5);

$stdin = fopen('php://stdin', 'r');
$stdlog = fopen('/var/log/asterisk/agitest.log', 'a');
$debug = 0;

function read() {
global $stdin;
$input = str_replace("\n", "", fgets($stdin, 4096));
dlog("read: $input\n");
return $input;
}

function write($line) {
dlog("write: $line\n");
echo $line."\n";
}

function dlog($line) {
global $debug, $stdlog;
if ($debug) fputs($stdlog, $line);
}

// parse agi headers into array
while ($env=read()) {
$s = split(": ",$env);
$agi[str_replace("agi_","",$s0)] = trim($s1);
if $env == "") {
break;
}
}

$vmbox = $_SERVER["argv"][1];
$vmbox = trim($vmbox);
$parts = split("@",$vmbox);


$pwauth = 0;

$fp = fopen("/etc/asterisk/voicemail.conf","r");
while ($s = fgets($fp))
{
if ($s{0} == ";") continue;
$s = trim($s);
if (preg_match("/^\[(.*)\]/i", $s, $match))
{
if (strtolower($match[1]) == strtolower($parts[1]))
{
$right = 1; dlog($s."\n");
} else {
$right = 0;
}
}
if ($right && preg_match("/^(".$parts[0].")\s*\=\>\s*(\d*)/",$s,$match))
{
if (strtolower($match[1]) == strtolower($parts[0]))
{
$pwauth = $match[2]; dlog($pwauth."\n");
fclose($fp);
}
}
}

if ($pwauth) {
write("EXEC Authenticate $pwauth");
$result = read();
$resultcode = split("=", $result);
if ($resultcode[1] == -1)
{
write("Hangup");
read();
}
} else {
write("Hangup");
read();
}

// clean up file handlers etc.
fclose($in);
fclose($stdlog);
exit;

?>


extensions.conf - example

exten => 120,1,Answer()
exten => 120,2,AGI(vm-pw.agi,2205@pstn)
exten => 120,3,Playback(lots-o-monkeys)

The only argument to this AGI is the extension and voicemail context to use. It uses "Authenticate" to get the password.
Created by: Andre_C10002, Last modification: Sat 10 of Jun, 2006 (07:44 UTC) by ghenry
Please update this page with new information, just login and click on the "Edit" or "Discussion" tab. Get a free login here: Register Thanks! - Find us on Google+