Friday, September 30, 2011

Design Long Distance Access Code System in Asterisk

Why Long Distance Access code?
When any organization has hundreds and thousands of users, they don't want each and every user to have long distance dialing access. So, they requests telco to setup set of LD access codes and organization distribute those access codes to the desired users. It's just like password to access long distance dialing from desk phones.

You loose the control when teclo have the control over Long Distance Access codes for your PRI/T1/SIP lines. I was undergoing the same problem. So, I decided to design my own LD access code system.

Step1: Create a file called ldcodes.conf in /etc/asterisk directory and list all the long distance codes in there.

#vi ldcodes.conf
2545368 ; For Mr. Smith
2549347 ; For Mr. Nelson
2545238 ; For Mrs. Ann
2549638 ; For Mrs. Jessica


(Here we created 7 digit LD codes. Those are the LD codes provided to the respective users. Good thing with this is, if Mr. Smith's LD access code is compromised by some other users, you can simply delete that code and create new one for Mr. Smith. You don't have to call your Telco and go thru' the pain of 2-3 weeks to get it done)

Step2: Create a dialplan for long distance dialing in /etc/asterisk/extensions.conf

exten => _91XXXXXXXXXX,1,Verbose(1,--- ${STRFTIME(${EPOCH},,[%m/%d/%Y-%H:%M:%S])} Dialing Long Distance Number: ${EXTEN:1})
same => n,Set(counter=0)
same => n(Pass),read(ldcode,en/enter-long-distance-code)
same => n,Set(counter=$[${counter}+1])
same => n,Set(LDCODES=${SHELL(/usr/bin/less /etc/asterisk/ldcodes.conf|/usr/bin/grep ${ldcode}|/usr/bin/wc -l)})
same => n,Verbose(1,--- Entered code is ${ldcode} and LDCODES is ${LDCODES})
same => n,Verbose(1,--- Shell command executed ${SYSTEMSTATUS} )
same => n,GotoIf($[${counter} >= 5]?Hangup:)
same => n,GotoIf($[$[${LDCODES}=1] & $[${ldcode}>999999]]?Success:Pass)
same => n(Success),Dial(SIP/telco_trunk-out/${EXTEN:1})
same => n(Hangup),Hangup()



read() command asks the user to enter the long distance code. [Make sure that you make the recording enter-long-distance-code and place it under /var/lib/asterisk/sounds/en]

Set(MyVariable=${SHELL()) is the very important and useful command. This command returns the output of SHELL() to a MyVariable. In above case, it is LDCODES

In GotoIf() we are checking if the SHELL() command returned 1 or not & if LDcode provided by user is greater than 999999. If statement is true, go to SUCCESS else go to PASS label.
[Note: above GotoIf() logic always ensures that 7 digit matching is done. You can also achieve this by checking if user entered 7 digit LDcode or not]

To prevent the caller to make unlimited guess, we can limit the password attempts to 5 by using the counter as illustrated above in the dialplan (they are in black).



You can refer to
http://leifmadsen.wordpress.com/2009/07/17/howto-read-a-value-from-a-file-and-say-it-back/
It has good explanation of reading a file in asterisk.

5 comments:

  1. If you add

    same => n,Set(CDR(userfield)=${ldcode})

    this will write the ldcode to your mysql asterisk CDR database. Great script, thank you for sharing!

    ReplyDelete
  2. how about using 1.6 how would this differ?

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Order of count incrementation and checking seems out of order. If left alone user is prompted for access code and dropped on 5th try even if code was entered correctly. Code below will allow 3 failed attempts then call is sent to hangup.

    exten => _91XXXXXXXXXX,1,Verbose(1,--- ${STRFTIME(${EPOCH},,[%m/%d/%Y-%H:%M:%S])} Dialing Long Distance Number: ${EXTEN:1})
    same => n(Pass),Set(counter=$[${counter}+1])
    same => n,GotoIf($[${counter} >= 4]?Hangup:)
    same => n,read(ldcode,en/enter-long-distance-code)
    same => n,Set(LDCODES=${SHELL(/usr/bin/less /etc/asterisk/ldcodes.conf|/usr/bin/grep ${ldcode}|/usr/bin/wc -l)})
    same => n,Verbose(1,--- Entered code is ${ldcode} and LDCODES is ${LDCODES})
    same => n,Verbose(1,--- Shell command executed ${SYSTEMSTATUS} )
    same => n,GotoIf($[$[${LDCODES}=1] & $[${ldcode}>999999]]?Success:Pass)
    same => n(Success),Dial(SIP/telco_trunk-out/${EXTEN:1})
    same => n(Hangup),Hangup()

    ReplyDelete
  5. Awesome article, it was exceptionally helpful! I simply began in this and I'm becoming more acquainted with it better! Cheers, keep doing awesome! door access system to buy

    ReplyDelete