FreePBX 2.10 or 2.11 & Asterisk dynamic phone locking application

(image courtesy of


We had a couple of clients requested this function of on the fly locking and unlocking functionalities independent of the phone manufacturer. This means also web phones, softphones and mobile softphones and what not. There are so many unmaintained hacks out there and most of the stuff in contributed modules are either not working or they cannot integrate properly or they’ve not been maintained for newer versions of FreePBX. So I decided to write a small dialplan with the relevant recordings for you to use straight off. Please however read the following and as usual please send your feedbacks if something didn’t work or just to say hi 🙂

Notes and disclaimers

  1. This specific dialplan and instructions are designed for FreePBX 2.10 or higher and Asterisk version 1.8 or higher. You most probably can use them for older versions, but it is not covered in this guide though
  2. It is extremely important to define and test out the emergency numbers before rolling out. Malaysian emergency number is 999, change or add more as you wish, add as many exceptions by just copy pasting that 999 line and add the copied line below 999 and modify accordingly.
  3. Please ensure you test this, as this hooks the first priority of any given device (extension) in FreePBX, it may break custom context* module. So if this is broken, no devices/extensions can call out
  4. It uses AstDB to store the pin numbers, so drama there.
  5. It is tested with extensions mode or device and user mode
  6. It comes with the recordings which you can download from here
  7. I do not guarantee the functionality with heavily modified FreePBX setups
  8. This assumes all extensions uses the from-internal context. If you use custom context modules and name your context say “National-Calls” for instance, then whatever you see in the [from-internal-custom] needs to be also set in [National-Calls-Custom] as the custom context module includes custom dialplans too.
  9. You may use BLFs to indicate locking statuses, but the hints “declared” done inside from-internal[-custom] contexts or which context you’ve set as the hints context, i.e. subscribecontext value in sip.conf or sip_general_custom.conf or the SIP Settings in Settings. Leave it default(unset) if you’re not sure. You have to define for each extension you wan’t to use BLFs, in this example below, its extension 8001
  10. TTS sounds courtesy of AT&T Natural Voices® Text-to-Speech Demo
  11. Parts of the dialplan were taken off various web sources, but mainly it came from forums
  12. We always have a master pin to ensure you can help those who’ve not remembered their PINS (of course, the other way is to list astdb entries for that extension)


  • Dial *159 to set phone lock
  • Dial any number you wish to dial and enter the pin to unlock
  • Unlock masterkey is 2606 incase someone forgets


Steps to get this working on an unmodified core of FreePBX 2.10, 2.11. Be sure to read instructions and notes inside the dialplan too.

  1. Edit the file in /etc/asterisk/extensions_custom.conf. Paste the following diaplan there:

    include => app-create-pin
    ;;;;;;;;;;;;;;;; Emergency and exceptions;;;;;;;;;;;;;;;
    exten => 999,1,Goto(from-internal,${EXTEN},1)
    exten => 8001*159,hint,Custom:8001*159
    exten => _.,1,Macro(predial-checks)
    exten => s,1,NoOp(Phone locking module starting..)
    exten => s,n,Gotoif($[${DB_EXISTS(AMPUSER/${CALLERID(num)}/locked)}=0]?proceed)
    exten => s,n,Set(PINCOUNT=0)
    exten => s,n(readpin),Read(PIN,custom/lockunlock,,,1,5)
    exten => s,n,Set(MASTERUNLOCKER=2606)
    exten => s,n,GotoIf($[${PIN}=${MASTERUNLOCKER}]?unlocked)
    exten => s,n,Gotoif($[${PIN}=${DB(AMPUSER/${CALLERID(num)}/locked)}]?unlocked)
    exten => s,n,Set(PINCOUNT=$[${PINCOUNT}+1])
    exten => s,n,GotoIf($[${PINCOUNT}>2]?toomanyerros)
    exten => s,n,Playback(custom/wrongpintryagain)
    exten => s,n,Goto(readpin)
    exten => s,n(endit),Playback(an-error-has-occured)
    exten => s,n,Playback(terminating)
    exten => s,n,Hangup(16)
    exten => s,n(toomanyerros),Playback(custom/toomanyerrors)
    exten => s,n,Playback(terminating)
    exten => s,n,Hangup(16)
    exten => s,n(unlocked),NoOp(${DB_DELETE(AMPUSER/${CALLERID(num)}/locked)})
    exten => s,n,Set(DEVICE_STATE(Custom:${CALLERID(num)}*159)=NOT_INUSE)
    exten => s,n,Playback(custom/unlockedsuccess)
    exten => s,n,MacroExit()
    exten => s,n(proceed),NoOp(${DB_DELETE(AMPUSER/${CALLERID(num)}/locked)})
    exten => s,n,MacroExit()

  2. [app-create-pin]
    exten => *159,1,NoOp(In Set Lock)
    exten => *159,n,Read(PIN1,custom/enterpinnumber,,,,)
    exten => *159,n,Read(PIN2,custom/confirmpinnumber,,,,)
    exten => *159,n,Gotoif($[${PIN1}=${PIN2}]?setpin)
    exten => *159,n,Playback(custom/invalidverify)
    exten => *159,n,Hangup(16)
    exten => *159,n(setpin),Set(DB(AMPUSER/${CALLERID(num)}/locked)=${PIN1})
    exten => *159,n,Set(DEVICE_STATE(Custom:${CALLERID(num)}*159)=RINGING)
    exten => *159,n,Playback(custom/locksuccess)
    exten => *159,n,Playback(goodbye)
    exten => *159,n,Hangup(16)

  3. Note, if you already have something in [from-internal-custom], the ones I add above needs to be right on top. The code for locking is inside [app-create-pin] and the code for checking and unlocking is inside [macro-predial-checks].
  4. Download and store the recordings in the /custom folder
    # cd /var/lib/asterisk/sounds/custom
    # wget  -O phonelocker.tar.gz && tar -zxvf phonelocker.tar.gz
  5. Change ownership of these files to the asterisk daemon user/group you’re running with, in many cases and also in my case its “asterisk/asterisk”
    # chown asterisk:asterisk confirmpinnumber.wav
    # chown asterisk:asterisk enterpinnumber.wav
    # chown asterisk:asterisk invalidverify.wav
    # chown asterisk:asterisk locksuccess.wav
    # chown asterisk:asterisk lockunlock.wav
    # chown asterisk:asterisk toomanyerrors.wav
    # chown asterisk:asterisk unlockedsuccess.wav
    # chown asterisk:asterisk wrongpintryagain.wav
  6. Reload asterisk dialplans
    # asterisk -rx “dialplan reload”
  7. Test by dialing *159, lock ya phone!
  8. Dial anywhere and unlock it with the pin you set in item 6 just now.
  9. Be sure to test dialing your emergency numbers
  10. If you want to use BLFs, here’s a screenshot of blfs using a Yealink phone, the key item here is 8001*159 as the hint code for the phone, 8001.
  11. Hints are currently set to blink when locked or the DEVICE_STATE of “ringing”.

Good luck and happy securing your phones!


  1. Hello,

    Thanks for this script, it works perfectly.

    However when I make an external call, instead of my DID, it the Head number which appears on the recipient phone.

    can you advise pls.

  2. What "head"? There's no such thing!

    This script doesn't change caller ID, that's something in FreePBX/Asterisk that you need to trace

Comments are closed.