Asterisk, and other worldly endeavours.

A blog by Leif Madsen

#AstriCon 2011 Quote of the Conference (@abalashov)

I think the best quote I heard the entire time came from @abalashov (Alex Balashov) during the AstriDevCon when we were talking about Asterisk documentation, and how we might better organize it within the source.

We were discussing perhaps moving some of the existing configuration file examples to a manpage, and Alex piped up to say, “Manpages are a vestige of our glorious, prehensile, curly-tailed past.”

There wasn’t much left to be said after that🙂

Written by Leif Madsen

2011/10/30 at 10:46 am

#AstriCon 2011: Cooking With Asterisk

My other presentation at AstriCon 2011 was Cooking With Asterisk, an overview of some dialplan snippets (pulled from the Asterisk Cookbook).

http://leifmadsen.com/sites/default/files/AstriCon 2011 – Cooking With Asterisk.pdf

Written by Leif Madsen

2011/10/28 at 8:19 am

Posted in Asterisk

#AstriCon 2011: Building a Distributed Call Centre

The presentation and configuration files from my presentation at AstriCon 2011 today is available at:

http://leifmadsen.com/sites/default/files/AstriCon 2011 – Building a distributed call centre.zip

Written by Leif Madsen

2011/10/26 at 2:15 pm

AstriCon presentation today at 11:40am

I’ll be speaking at AstriCon today (and tomorrow) about building a distributed call centre. The presentation will be 35 minutes long and will contain a set of slides that moves you from an existing traditional PBX system up through a distributed model (which happens to use a call centre as the example system).

A PDF of the presentation along with the configuration files from the demo will be available on my website after the presentation. I’ll post links to the files on my blog here shortly after the presentation finishes.

Hope to see you there!

Written by Leif Madsen

2011/10/26 at 11:36 am

Return just PID of script with ‘ps’ and ‘awk’

Today I ran into an issue where I am running a python script that I needed to get the process ID (PID) of, but that the process was being output with a space between ‘python’ and the actual script name (in this case, jiraircbot.py).

I’m sure it’s totally overkill and there is a much easier way I didn’t find to do this, but after some scouring of The Google, I found something that works! (The purpose of this was to kill off a rogue script process each night so I could restart it.)

Here is what the output looks like with just ps aux | grep python

# ps aux | grep python
root      1120  0.0  0.2  50176  4380 ?        Sl   Aug04  24:52 /usr/bin/python /usr/bin/fail2ban-server -b -s /var/run/fail2ban/fail2ban.sock
root     18182  2.2  1.5  35328 32148 pts/0    S    08:21   0:11 python jiraircbot.py
root     18219  0.0  0.0   3328   804 pts/0    S+   08:29   0:00 grep python

A little bit more data than I wanted, plus of course ‘grep python’ is always going to be returned if I just use grep straight up. Putting many pieces together from a few websites, this is what I came up with to just return the PID of the jiraircbot.py script:

ps -eo pid,command | grep "jiraircbot.py" | grep -v grep | awk '{print $1}'

What I’m doing, is controlling what is returned, so in this case have ps just return the pid and command fields. Run that through grep to just get the script I wanted, pipe that back through grep to remove the line including grep python and then pipe that through awk to just return the first field (which would be the pid of the process I wanted).

All in all, a nice hack🙂

Written by Leif Madsen

2011/09/15 at 7:34 am

Posted in Being Productive, Programming

Tagged with , , , , ,

Using Dialplan Functions: AES_DECRYPT() and AES_ENCRYPT()

I  recently asked on twitter how many people would be interested in a set of blog posts that focused on how to use the various dialplan functions in Asterisk, and I got quite a positive response. I posted that shortly before getting married, and now that I’m back into the groove of things, I’m going to take a shot at posting a bunch of content focused around Asterisk dialplan functions. If you don’t know what Asterisk dialplan functions are, head on over to the online version of Asterisk: The Definitive Guide (3rd edition) (or buy it) and read the section on dialplan functions. If you’re still starting out with Asterisk, I highly suggest you start with the dialplan basics chapter.

Today we’ll look at the first 2 dialplan functions in my list: AES_DECRYPT() and AES_ENCRYPT()

The AES_DECRYPT() and AES_ENCRYPT() functions work by passing strings to the functions, and they return a result. If you pass an unencrypted string to the AES_ENCRYPT() function it will return an encrypted string; vice-versa for the AES_DECRYPT() function. The two functions operate by passing a string and a key where the result is encoded  in base64.

Use case for these functions probably makes the most sense when you need to store data outside of the dialplan, perhaps passwords, pins, or other data passed in by the caller, but which you want to secure when you go to store it. Let’s take an example where we create some dialplan that allows a caller to set their pin and store it in the database. For the sake of simplicity I’m not going to add any error checking (like to verify we really have data to work with, allow the caller to verify their extension, etc.):

exten => *88,1,NoOp()
 same => n,Playback(silence/1)
 same => n,Read(UserExtension,extension,3)                  ; read persons 3 digit extension unmber
 same => n,Verbose(2,Extension number: ${UserExtension})
 same => n,Read(PinEntry,agent-pass)                        ; ask for a pin number
 same => n,Verbose(2,Pin number: ${PinEntry})
 same => n,SayDigits(${PinEntry})                           ; say pin back to caller
 same => n,Set(DB(pin/${UserExtension})=${PinEntry})        ; store pin in the AstDB
 same => n,Playback(vm-goodbye)
 same => n,Hangup()

After the user enters their extension and pin, we store it in the AstDB. We can verify it was stored correctly by checking from the Asterisk CLI:


scrappy*CLI> database show pin
/pin/100 : 1234
1 results found.

Now let’s modify our dialplan to store the pin in the database using a value returned from AES_ENCRYPT().

exten => *88,1,NoOp()
 same => n,Playback(silence/1)
 same => n,Read(UserExtension,extension,3)
 same => n,Verbose(2,Extension number: ${UserExtension})
 same => n,Read(PinEntry,agent-pass)
 same => n,Verbose(2,Pin number: ${PinEntry})
 same => n,SayDigits(${PinEntry})
 same => n,Set(SpecialKey=1234qwerasdfzxcv)
 same => n,Set(EncryptedPin=${AES_ENCRYPT(${SpecialKey},${PinEntry})})
 same => n,Set(DB(pin/${UserExtension})=${EncryptedPin})
 same => n,Playback(vm-goodbye)
 same => n,Hangup()

And we can see the encoded string stored in the database:


scrappy*CLI> database show pin
/pin/100 : Je2G/qyHuGVKgvvXDwXjHA==
1 results found.

Of course anyone who has access to the AstDB from the Asterisk CLI is also going to have access to the Asterisk dialplan, so you’ll have to do a better job than I have here of hiding the secret key being used for encrypting the data. Really all we’re trying to do here is not make the list of pins and data in our AstDB quite so obvious. We could of course not use AstDB at all, and store the data remotely where we know people will have access to the data, but not access to the secret key on our Asterisk server.

Now lets look at the inverse by decoding the pin to authenticate someone.

exten => *77,1,NoOp()
 same => n,Playback(silence/1)
 same => n,Read(UserExtension,extension,3)                     ; get users extension
 same => n,Set(EncryptedPin=${DB(pin/${UserExtension})})       ; get encrypted pin from AstDB
 same => n,Read(PinEntry,agent-pass)                           ; get pin from user
 same => n,Set(SpecialKey=1234qwerasdfzxcv)
 same => n,Set(DecryptedPin=${AES_DECRYPT(${SpecialKey},${EncryptedPin})})                          ; decrypt the pin
 same => n,Playback(${IF($["${PinEntry}" = "${DecryptedPin}"]?pin-number-accepted:pin-invalid)})    ; if pin is correct, play number accepted, else, pin invalid
 same => n,Playback(vm-goodbye)
 same => n,Hangup()

That’s it for now. Leave a comment if you like this format, and if you found this article useful. Thanks!

Written by Leif Madsen

2011/09/09 at 8:28 am

Asterisk 10 == Asterisk 1.^H^H10

In case you missed it, the next version of Asterisk is now in beta, and at the same time, has undergone a minor version numbering scheme. As it is unlikely that Asterisk will ever have a 2.0 release since for years now, that has generally meant Asterisk would undergo a major underlying change in both how it was programmed and the user experience (and since it would be a major disruption to the Asterisk community), it was deemed unnecessary to utilize the 1. preamble in front of the version numbers.

Asterisk versioning has used the following as branch numbers over the years:

  • 1.0
  • 1.2
  • 1.4
  • 1.6.0
  • 1.6.1
  • 1.6.2
  • 1.8

The next version to have followed Asterisk 1.8 would have been Asterisk 1.10. Since it has been determined the prefix of 1. is now superfluous, it was simply dropped. So instead of the version following 1.8 being:

  • 1.8
  • 1.10

We now have…

  • 1.8
  • 10

This should hopefully lead to a slightly less confusing numbering scheme going forward as there will no longer be the skipped odd numbers. Kevin Fleming at Digium explains the reasons for dropping the leading ‘one dot’ in his blog post at http://blogs.digium.com/2011/07/21/the-evolution-of-asterisk-or-how-we-arrived-at-asterisk-10/

As Asterisk moves forward, this is how versions will look:

Asterisk branch versions (which signify major version increases) will increment singularly:

  • 10
  • 11
  • 12

Within each of those branches minor versions will be released for the time the branch is supported. (Information about the support level of Asterisk branches is available at https://wiki.asterisk.org/wiki/display/AST/Asterisk+Versions.) These would be the bug fixes that an Asterisk implementer/administrator would deploy. Some examples include:

  • 10.0.0
  • 10.1.0
  • 10.2.0
  • 10.3.0
  • 10.4.0

You’ll have noticed the implicit declaration of the ‘dot zero’ on the end of the version. In the past when a security release or regression is resolved for a tag, an additional version number is added to the end. Lets take Asterisk 10.2.0 as an example of a version that was to receive a change to the tag after initial release, perhaps for a security update. Instead of requiring administrators to update to a tag of Asterisk that has changes in addition to the security changes, a new tag with only the changes required to satisfy the resolution of the security issue are added.

(The mechanics of which are essentially to copy the existing tag to a new tag number, merge the changes, then repackage the new tag. The equivalent of copying the contents of one directory to another new directory, and making a single change.)

So for a security issue being resolved in Asterisk 10.2.0, there would be a release of Asterisk 10.2.1. If additional changes were made to the base tag of 10.2.0, then you would see:

  • 10.2.0
  • 10.2.1
  • 10.2.2

Only spot testing should be required for upgrades between 10.2.0 -> 10.2.1 -> 10.2.2. Of course more thorough testing between something like 10.2.0 and 10.3.0 would be required by the administrator.

Hopefully this helps alleviate any remaining confusion.

Written by Leif Madsen

2011/08/29 at 3:27 pm