LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Server
User Name
Password
Linux - Server This forum is for the discussion of Linux Software used in a server related context.

Notices


Reply
  Search this Thread
Old 11-26-2010, 10:16 AM   #1
PelliX
Member
 
Registered: Apr 2006
Location: Enschede
Distribution: Debian, Red Hat/Fedora, Solaris, DD-WRT, NetBSD, Mac OS8/9, Mac OSX, UMP/OS, ESX
Posts: 42

Rep: Reputation: 15
Asterisk DISA IVR


Hello,

I am having trouble solving an issue which I'm sure other people must have faced before:

I have Asterisk 1.2 running on a SPARC Solaris machine (I know there's a forum for that, but it doesn't directly relate to the issue at hand) with a number of extensions, queues and so on configured and working well. Recently I wanted to create an IVR including a PIN verification system, enabling a user to call the number, hear a message (welcome, enter your PIN, etc), enter his PIN in the DISA application and hear another message afterwards without any further input. To clarify, I can call the extension (IVR), hear the message and input my PIN, though after that I'm left with a dialtone and Asterisk waiting for me to enter a number(extension to call). If I do this, it forwards me correctly, though I'd prefer an intermediate step including a message for the user. The idea is the following:

User calls number.
User is greeted with 'Enter your PIN,etc'.
User enters PIN code, followed by a '#'.
User hears another message 'Thank you. Now you can...etc'.
User then provides further input, etc.

Here's an excerpt from my extensions.conf:

Code:
; Lights control
exten => 9994,1,Answer
exten => 9994,2,Playback(welcome)
exten => 9994,3,Playback(beep)
exten => 9994,n,DISA(4321|lcontrol)
;exten => 9994,n,Playback(code_accepted)
exten => 9994,105,Hangup

[lcontrol]
exten => s,1,Answer
exten => s,2,Playback(lights_explain)
exten => s,n,WaitExten
; turn off lights
exten => 0,1,Answer
exten => 0,n,Playback(code_accepted)
exten => 0,n,TrySystem(/usr/bin/lights_off.sh)
exten => 0,n,Playback(beep)
exten => 0,n,Playback(lights_off)
exten => 0,n,Wait(2)
exten => 0,n,Hangup
; turn on lights
exten => 1,1,Answer
exten => 1,n,Playback(code_accepted)
exten => 1,n,TrySystem(/usr/bin/lights_on.sh)
exten => 1,n,Playback(beep)
exten => 1,n,Playback(beep)
exten => 1,n,Playback(lights_on)
exten => 1,n,Wait(2)
exten => 1,n,Hangup
Obviously, I could simply define an extension as the PIN code, though this seems rather crude. The way that I understand it, is that DISA is designed to 'forward' the call to a context, NOT an extension or back to the current/previous context. I know that you could also use the Authenticate() application, though in that case I would either have to overwrite the default female voice or live with two different voices (of different sexes!) in one single IVR, and I'm reluctant to overwrite 'her'. I also don't want to use VMauthenticate() either for the same reason, and the fact that not all registered users should be able to pass the DISA() step with only their own credentials (the PIN would be a secret, available to a limited number of people).

Update: I have a working example defining the PIN as an extension followed by a hash. This is the exact desired functionality though I'd love to see a better way of implementing this:

extensions.conf:
Code:
; Lights control
exten => 9994,1,Answer
exten => 9994,2,Playback(lights_control)
exten => 9994,3,Playback(beep)
exten => 9994,4,WaitExten
exten => 4321#,1,Answer
exten => 4321#,2,Playback(code_accepted)
exten => 4321#,n,Goto(lcontrol|s|1)
exten => 4321#,n,Hangup
exten => i,1,Wait(4)
exten => i,2,Playback(code_invalid)
exten => i,3,Goto(queues|9994|2)


[lcontrol]
exten => s,1,Answer
exten => s,2,Playback(lights_explain)
exten => s,n,WaitExten
; turn off lights
exten => 0,1,Answer
exten => 0,n,TrySystem(/usr/bin/lights_off.sh)
exten => 0,n,Playback(beep)
exten => 0,n,Playback(lights_off)
exten => 0,n,Wait(2)
exten => 0,n,Hangup
; turn on lights
exten => 1,1,Answer
exten => 1,n,TrySystem(/usr/bin/lights_on.sh)
exten => 1,n,Playback(beep)
exten => 1,n,Playback(beep)
exten => 1,n,Playback(lights_on)
exten => 1,n,Wait(2)
exten => 1,n,Hangup



If anyone as has any ideas (or solutions!) please let me know.

Kind regards,

PelliX

Last edited by PelliX; 11-26-2010 at 11:57 AM.
 
Old 11-30-2010, 07:32 AM   #2
PelliX
Member
 
Registered: Apr 2006
Location: Enschede
Distribution: Debian, Red Hat/Fedora, Solaris, DD-WRT, NetBSD, Mac OS8/9, Mac OSX, UMP/OS, ESX
Posts: 42

Original Poster
Rep: Reputation: 15
Well, after some analysis it became clear to me that Asterisk itself does not provide such functionality in a predefined way, and the obvious way to go is the AGI (Asterisk Gateway Interface). Although any programming language can be used for this, I decided to whip up a quick version in Perl:

Code:
#!/usr/bin/perl
# 
# This script verifies a user's PIN code to grant access to secured 
# systems and contexts.
#
# PelliX 2010
#
# Note that the numeric values from the $wait_for_digits() function
# are calculated by subtracting 48 when receiving numeric input, though
# the pound sign (or hash) is reported as 35 and the asterisk as 42.
#
use Asterisk::AGI;
use strict;

# location of PIN database and protected context
my $db = "/etc/opt/asterisk/PIN.db";
my $target_context = 'lcontrol';
my $source_context = 'queues';
my $source_exten = '7000';

my $AGI = new Asterisk::AGI;
my %input = $AGI->ReadParse();
my $callerid = $input{'callerid'};

$AGI->verbose('Initiating PIN check');
$AGI->stream_file('beep');

my $dig1 = ($AGI->wait_for_digit(-1) - 48);
my $dig2 = ($AGI->wait_for_digit(-1) - 48);
my $dig3 = ($AGI->wait_for_digit(-1) - 48);
my $dig4 = ($AGI->wait_for_digit(-1) - 48);
my $dig5 = ($AGI->wait_for_digit(-1));

my $pincode = $dig1.$dig2.$dig3.$dig4;
#$AGI->say_digits($pincode);
$AGI->verbose('PIN: '.$pincode);

my $result;
my $selection;
# if the PIN code was followed by a hash
if ($dig5 == 35)
	{
	open(PINDB, '<', $db);
	while (<PINDB>)
		{
		if ((substr $_, 0, 4) eq $callerid)
			{
			$result = "Found $callerid in DB, verifiying PIN";
			$AGI->verbose($result);
			if ((substr $_, 5, 4) eq $pincode)
				{
				$result = "Matched user $callerid with PIN $pincode in DB";
				$AGI->verbose($result);
				$AGI->stream_file('code_accepted');
				$AGI->stream_file('lights_explain');
				$selection = ($AGI->wait_for_digit(-1) - 48);
				# continue to protected context (and extension)
				# in this example there are only two choices; 0 and 1
				if ($selection < 2)
					{
					$AGI->set_priority('1');
        	                        $AGI->set_extension($selection);
                	                $AGI->set_context($target_context);
					}
					else
					{
					$AGI->set_priority('1');
					$AGI->set_extension($source_exten);
					$AGI->set_context($source_context);
					}
				}
				else
				{
				$result = "Failed to match user $callerid with PIN $pincode in DB";
				$AGI->verbose($result);
				$AGI->stream_file('code_invalid');
				$AGI->set_priority('1');
				$AGI->set_extension($source_exten);
				$AGI->set_context($source_context);
				}
			}
		}
	}
	else
	{
	$result = "PIN entry not followed by hash";
	$AGI->verbose($result);
	$AGI->stream_file('code_invalid');
	$AGI->set_priority('1');
	$AGI->set_extension($source_exten);
	$AGI->set_context($source_context);
	}

close(PINDB);

$AGI->verbose('PIN verification ended');
exit;
Note that in this case the extension that the user needs to dial has changed to 7000 for cosmetic reasons. The database can be implemented in MySQL or any other form of database by adding the relevant logic to the Perl script and including the required libraries. In this example the database consists of a plain text file, referred to as $db in the script, with the following layout ('callerid:PIN'):

Code:
3045:1234
4247:4321
2199:9072
Additionally, there was a slight modification to the dialplan for extension 7000:

Code:
[queues]
; Lights control (AGI)
exten => 7000,1,Answer
exten => 7000,2,Playback(lights_control)
exten => 7000,3,EAGI(PIN.agi)
exten => i,1,Wait(1)
exten => i,2,Hangup

Thanks,

PelliX

Last edited by PelliX; 12-01-2010 at 06:25 AM. Reason: bad grammar!
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
DISA STIG Compliance Scripts/RPM's zcrxsir88 Linux - Security 21 03-17-2017 12:32 PM
SUSE 10 and DISA STIGS question CDAWG Linux - Security 1 09-24-2010 05:10 PM
LXer: Voice Menus and IVR in AsteriskNOW LXer Syndicated Linux News 0 01-19-2009 09:20 AM
DTMF applications for IVR surfing topcat Programming 7 08-14-2007 03:37 AM
point me in a right direction for ivr solution nephish Linux - General 0 06-02-2006 12:43 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Server

All times are GMT -5. The time now is 05:24 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration