Created
August 7, 2023 23:11
-
-
Save hgaibor/c8d65e5b6c56ffc7b7f1d73e127641aa to your computer and use it in GitHub Desktop.
targeted-spy-with-cos-and-exts-restrictions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
; Feature code + Class of Service implementation to allow certain users to spy/whisper/barge on | |
; a specified extension. | |
; NEW: Ability to set the list of extensions that can be spied for each extension. | |
; This will use the accountcode variable inside of the extension --> [advanced] tab | |
; Extensions list will be separated by & (eg: 100&200&201...) MAX limit 255 chars!! | |
; | |
; Latest version: | |
; https://gist.github.com/hgaibor/ | |
; | |
; Forked from: | |
; https://gist.github.com/hgaibor/82433116540f15ab345b2914500abb0d | |
; https://gist.github.com/hgaibor/6a170c150cf9dec607620aa44d78fcd0 | |
; | |
; Usage and install instructions: | |
; 1. On FreePBX/PBXact GUI, Create a Custom Destination that points to the [custom-spy-with-cos-and-restrictions] context. | |
; Fill the interface fields with the values after the --> : | |
; 1.1 Target --> custom-spy-with-cos-and-restrictions,s,1 | |
; 1.2 Description --> Put a brief description | |
; 1.3 Notes --> Put your detailed comments here | |
; 1.4 Return --> no | |
; | |
; 2. Create a Misc Application that will point to created custom destination above. | |
; This destination will have the feature code you choose and will allow you to set the permissions over the | |
; Class of Service module. | |
; 2.1 Enable --> Yes | |
; 2.2 Description --> Spy with permissions feature code | |
; 2.3 Feature Code --> *557 (you can change this to whatever code needed) | |
; 2.4 Destination --> SELECT Custom Destination created above | |
; | |
; 3. Create Class of Service rules to DENY all users to use this code and allow the ones you need. | |
; Since you used the Misc Application module to assign the feature code, it will appear under the | |
; Class of Service --> [Feature codes] tab | |
; | |
; 4. Put Custom Dialplan at (GUI can be used using Config edit module): | |
; /etc/asterisk/extensions_custom.conf | |
; Dial feature code assigned under Misc Application to start in spy mode. While spying on | |
; active channel use the following dtmf input to toggle modes: | |
; dtmf 4 - spy mode | |
; 5 - whisper mode | |
; 6 - barge mode | |
; | |
; 5. Set the list of extensions that can be spied by the current extension, in the 'accountcode' field at the [advanced] tab. | |
; format wil be the following: '100&101&200&201&2000' and so on.. separate extensions with & | |
; extensions will be able to spy every other extension that is listed under its accountcode, | |
; unless they are prevented from using the feature code by the Class of service module permissions. | |
; | |
; This is default behavior mentioned in https://wiki.asterisk.org/wiki/display/AST/Application_ChanSpy | |
; | |
; License: GNU GPL2 | |
; | |
; Version History | |
; 2023-08-07 First public commit by hgaibor | |
; For testing spy level restrictions without COS, if you don't want to perform steps 1 to 3 mentioned above uncomment this | |
; block of code and use the code combination of your preference | |
;[from-internal-custom] | |
;exten => *557,1,Noop(Entering user defined context custom-spy-with-cos-and-restrictions in extensions_custom.conf) | |
;exten => *557,n,GoTo(custom-spy-with-cos-and-restrictions,s,1) | |
[custom-spy-with-cos-and-restrictions] | |
exten => s,1,Noop(Entering user defined context custom-spy-with-cos-and-restrictions in extensions_custom.conf) | |
; Get info on the originating extension | |
exten => s,n,Set(__SPY_EXT=${CALLERID(num)}) ; numeric spy level permission, will allow spy if this is greated than the SPIED_EXT accountcode value | |
exten => s,n,noop(Dialer Spy ext: ${SPY_EXT}) | |
; Get info on the extension that will be spied | |
exten => s,n,Read(__SPIED_EXT,please-enter-the&extension&number&followed_pound) | |
exten => s,n,noop(Spied ext: ${SPIED_EXT}) | |
exten => s,n,GoTo(check-spy-restrictions,s,1) | |
[check-spy-restrictions] | |
; This context will use the value set up in extensions Account Code in order to determine the extensions this user can spy | |
; It will allow spying on extensions listed at current extensions accountcode field. | |
; NOTE, Account code MAX lenght is 255 chars, keep this in mind, as it will count the & signs as part of this lenght | |
exten => s,1,Noop(Entering user defined context check-spy-restrictions in extensions_custom.conf) | |
exten => s,n,Set(SPY_EXTS=${DB(AMPUSER/${SPY_EXT}/accountcode)}) ; Checking SPY EXTS, separated by & sign. Will allow spy if target extension is present on this list | |
exten => s,n,Set(SPY_EXTS=${STRREPLACE(SPY_EXTS,&,\,)}) ; comma delimited list of extensions | |
exten => s,n,ExecIf($[!${LEN(${SPY_EXTS})}]?Set(SPY_EXTS=0)) | |
exten => s,n,noop(Dialer allowed spy extensions: ${SPY_EXTS}) | |
; step thru each extension in the list and compare if it matches spied extension | |
exten => s,n,While($["${SET(SPY_EXT=${POP(SPY_EXTS)})}" != ""]) | |
exten => s,n,noop(SPY_EXT: ${SPY_EXT}) | |
exten => s,n,GotoIf($["${SPY_EXT}"="${SPIED_EXT}"]?AllowSpy) ; if an active channel is found exit the loop | |
exten => s,n,EndWhile() | |
exten => s,n,GoTo(DenySpy) | |
exten => s,n,Hangup() | |
exten => s,n(AllowSpy),noop(Allowed spy from ext ${SPY_EXT} to ${SPIED_EXT}) | |
exten => s,n,GoTo(targeted-chanspy,${SPIED_EXT},1) | |
exten => s,n,Hangup() | |
exten => s,n(DenySpy),noop(DENIED! spy from ext ${SPY_EXT} to ${SPIED_EXT}) | |
exten => s,n,Playback(silence/1&sorry-cant-let-you-do-that&silence/1) | |
exten => s,n,Hangup() | |
exten => h,n,Hangup() | |
exten => s,n,Hangup() | |
exten => T,n,Hangup() ; timeout destination | |
[targeted-chanspy] | |
exten => _.,1,Noop(Entering user defined context targeted-chanspy in extensions_custom.conf) | |
exten => _.,n,Set(TIMEOUT(absolute)=3600) ; prevent hung channel by setting 1 hour timeout recommended if using infinite loop | |
exten => _.,n,Answer | |
exten => _.,n(once-upon-a-time),Wait(1) | |
exten => _.,n,set(spy_target=) ; initialize target var | |
; get list of dialable devices for extension | |
exten => _.,n,Set(DEVS=${DB(AMPUSER/${EXTEN}/device)}) ; & delimited list of devices | |
exten => _.,n,Set(DEVS=${STRREPLACE(DEVS,&,\,)}) ; comma delimited list of devices | |
; step thru each device and look for an active channel | |
exten => _.,n,While($["${SET(DEV=${POP(DEVS)})}" != ""]) | |
exten => _.,n,noop(dev: ${DEV}) | |
; using a regex of SIP/${EXTEN}- will match both SIP and PJSIP channels, and the trailing - character should | |
; help to ensure there is only a single match. If multiple channels are returned the chanspy application will fail | |
exten => _.,n,set(spy_target=${CHANNELS(SIP/${DEV}-)}) | |
exten => _.,n,ExecIf($["${spy_target}"!=""]?ExitWhile) ; if an active channel is found exit the loop | |
exten => _.,n,EndWhile() | |
exten => _.,n,ExecIF($["${spy_target}"!=""]?ChanSpy(${spy_target},dnqE)) ; q option suppresses channel announce on barge | |
exten => _.,n,Hangup() ;comment this line with a semicolon to do infinite loop | |
exten => _.,n,GoTo(once-upon-a-time) | |
exten => _.,n,Hangup() | |
exten => h,n,Hangup() | |
exten => s,n,Hangup() | |
exten => T,n,Hangup() ; timeout destination |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment