Link Active Directory, Asterisk, and OpenFire

We are friends among themselves Active Directory, Asterisk IP telephony server and OpenFire Jabber-server.



I will not touch on the installation of everything separately - everything is well described and it works individually wonderfully. I’ll write how I combined all this together, what I came across and what I did.

Disposition:


There is a domain controller dc.steepler.local ( 10.10.8.200 ). Domain, respectively - steepler.local. The server has users, beaten up to departments, etc. What is important - each user in the “telephone” column has his number on the Asterisk server.

There is an installed Asterisk VoIP server ( 10.10.8.98) All users are connected via SIP, respectively devices, in the understanding of Asterisk, they have the type SIP / XXX (where XXX is an extension number). At the time of writing, the server was installed long ago and has already been subjected to serious settings. That is why the work was not brought to its logical end - the logical end would be the automatic generation of the SIP terminal device configuration and dial plan. Unfortunately, I was afraid that I would have to seriously rewrite the existing configuration, and in any case, the automatic generation of the dial plan that exists in our organization and has many interactive menus and other customizations will not be interesting to the reader who is faced with the task, first of all, connect the server together. Where to go next will be clear.

So, there is Asterisk with the FreePBX frontend installed, which greatly complicated the task. Because FreePBX has the habit and need to overwrite all configuration files on top after making any changes to the web interface. That is, we can change the configs from the command line, but as soon as we change something later through the web-face, the configs will be erased by FreePBX as a decent frontend. Of course, the creators of the shell did not rely on their genius and left the opportunity for fine-tuning. This possibility is realized through loading additional contexts with the suffix “-custom” (which, in the end, turned out to be enough), or using “override” configs that rigidly record the changes you need. But, you need to understand that what is written in the custom or override config will work in your opinion, regardless of the FreePBX web interface. Either checkers, or go. That is, no matter what you twist there in the front-end, whatever you configure - if it touches custom settings - the settings from the files will work, not the front-end. That is why a lot of time was spent tracing the dialing plan generated by FreePBX - I wanted to find an entry point in such a procedure, the rigid binding of which would not affect further work.

There is, or rather, at the time of writing, there was no Jabber server. The choice, for inexplicable reasons, fell on OpenFire. In fact, the reasons are simple - OpenFire allows you to organize end-to-end (Kerberos / GSSAPI / SASL) user authorization. That is - the user does not need to enter either a login or password. If he passed domain authorization when entering windows - he is our client. When the client starts, it will substitute the user, send a request to the jabber server, and that one, using Kerberos, will confirm or deny the authenticity of the client's request. I will not go into details, it is important for us that authorization is transparent for the client, even if there is a policy of periodically changing the password in the domain. You should not generate stories about “stupid users” who write complaints to the authorities that something has stopped working for them, that they forgot to change the password. You just need to make sure that they have nowhere to stupid.
On OpenFire, you can install the standard Asterisk-IM plugin to communicate with Asterisk. It allows you to dynamically monitor user statuses, call IP phones, send notifications. Unfortunately, out of the box automation leaves much to be desired - despite the fact that end-to-end authentication and authorization of users through AD is possible and that information on the user's work phone is initially provided in AD, it is necessary to manually map AD / Asterisk users.
So. The Jabber server should be OpenFire, call jbrgseveren01.steepler.local, and work at 10.10.8.226 .
Further, I assume that I have Linux in the form of CentOS5, Asterisk 1.8.2, and the Win2008 domain controller. Although, this is absolutely not fundamental, it will work in other cases. Only the Asterisk version is critical - jabber support appeared only from the 1.6 branch, and PBX must be compiled with its support.

Tasks:


You need to install the Jabber server, configure it so that it takes the necessary users from the IM domain group. It is necessary in one way or another to automate the mapping of information about domain users, jabber users, Asterisk subscribers.
How does everything work out of the box? (Or pitfalls)
OpenFire accesses the domain controller via the ldap protocol and receives information from it about users who are allowed to use jabber.
Next, we need to install the Asterisk-IM plugin (two clicks in the OpenFire web face). In the plugin we need to register the Asterisk server. And, oh-shit, with your hands, re-register all users in the plan - login - phone number - its subscriber device in the understanding of Asterisk. After that, the plugin’s functionality will work - with the help of the native OpenFire client called Spark, users will be able to call each other using existing phones simply by clicking on the contact list. That is - I find a contact, I click “call” with my right mouse, a telephone starts to ring on my desk, I pick up the phone and, immediately, the telephone starts ringing at the contact. Moreover, when someone speaks on the phone, his status in the contact list changes to the corresponding one. Conveniently. But, the work of prescribing users must be automated.
We go further - there is a desire to send notifications of missed calls to jabber. It’s one thing when the lamp blinks on the phone and you have to go into the menu, see who called and it’s a completely different thing when you receive a message with the exact time and coordinates of the callers. Out of the box is not implemented in any way. That is, Asterisk, of course, easily clings to the OpenFire server in client or component mode, but the whole further task of processing and sending messages falls on your shoulders. Of course, not the sending work itself, but the explanatory work with Asterisk ;-) The most stupid solution here is to process each number individually. But, if there are more than five numbers, then it does not suit us. Plus, there is the possibility of users migrating between phones, adding new ones, deleting old ones. In addition, do not forget about FreePBX. If we rigidly define recruitment rules, we’ll lose the opportunity to use the wonderful web interface. In general, refuse rude. Not okay. We need to find an entry point in the dialing plan, write our own procedure, which will search for the corresponding domain user by the addressee’s number and, in the case of “no dialing”, send a message to jabber - they say, I called you on such and such a number with such and such a subscriber .

Getting down


The first thing we need is users. We create two users in the domain. We will need one for ldap authentication, the other for Kerberos. The first I called openfire, the second xmpp-openfire. Next - immediately create a group for jabber users (I have it called IM) and add the necessary users to it. We verify that all users who have an internal phone and are members of the IM group in the "phone number" field have exactly the extension number of the subscriber.
The second - we prescribe our future jabber server in DNS. We need both a forward and reverse zone. On the jabber server itself, configure the host name - write it in / etc / hosts :

127.0.0.1 localhost.localdomain localhost
10.10.8.226 jbrgseveren01.steepler.local  jbrgseveren01


We check from all sides with nslookup, everything should correctly resolve. Yes, the host name is in small case. It is important.
Third - install OpenFire according to the instructions - http://www.igniterealtime.org/builds/openfire/docs/latest/documentation/ldap-guide.html
Everything is simple there, there are no pitfalls. The maximum complexity is the formation of competent filters in the ldap request. We are connected through the first user. The output will be a functioning server with end-to-end authorization through AD. You can connect clients and work. But, our task is SSO: Single Sign On. We need the user to not have to think about his username and password for the client.
Getting started with Kerberos. Here we use the second user we created. Everything is described here -http://community.igniterealtime.org/docs/DOC-1060
Everything is a little more complicated, there are pitfalls. The main thing - REMEMBER ABOUT THE REGISTRY - everything matters. Write as in the manual - where are uppercase, there are uppercase, where are lowercase, there are lowercase. Do not forget to enter the server into the domain and check the fact of introduction. It is important!!!
Yes, I created keytab on the domain controller - everything worked for me. I did not use java tools.
Install Spark - the native OpenFire client, check - if SSO works - good. If not, you need to understand - look, write, see.
We go to the Asterisk server (do not forget - I have FreePbx, so I give the names of the files relative to its scheme; in the case of bare Asterisk, everything will be a little easier) and write in OpenFire user manager_custom.conf:
[openfire]
secret = XXXX
deny=0.0.0.0/0.0.0.0
permit=10.10.8.226/255.255.255.0
read = all
write = all

Now install the Asterisk-IM plugin. It is in the OpenFire web interface, in the tab with available plugins. We register on the appeared Asterisk-IM tab our VoIP server:
Server Name: AsteriskGSeveren01
ServerAddress: 10.10.8.98
Port: 5038 
Username: openfire
Password: XXXX

It is the turn to prescribe users with their hands ... We must go to the Phone Mappings tab and write, write, write. We restrict ourselves to a couple of users, we will check the work. In the Spark contact list, when you right-click on the username, the call option should appear. We select - our device should ring, when lifting the handset - the subscriber's device.
If everything works, good. If not, you need to understand - look, write, see.
Now begins what was spent most of the time.
We need to explain to Asterisk-IM that there are domain users and that Active Directory has all the necessary information.
Directly - no way. The plugin is old, its support has been discontinued - eat that is. And we have a MySQL database in which the plugin stores its information. The easiest way would be to extract information about OpenFire users from the database and palm off it with Asterisk-IM. But, since we have end-to-end authentication, OpenFire does not store anything in its database - it drags directly from the domain controller.
Good. We write a script that will cling to AD using the ldap protocol (we already have a user), drag information on domain users who are members of the IM group, and take out fields containing the full name, login and phone number. Then we form the SQL injection and push it into the Asterisk-IM database directly. Dumb crutch, but it works.
Two scripts came out - one I found ready here. It is written in perl - it pulls the info from the domain and, by the way, is able to display the finished sip.conf after the minimum editing. The second one, on the bash, calls the first one, dissects his conclusion (yes, I know that I’m a pervert, but since the task has already been solved by someone, I don’t have to fence), generates SQL injections and shoves everything into the database.
Wornly modified by users-from-AD.pl
#!/usr/bin/perl
# users.pl v1.1
#
# Script to generate asterisk 'users.conf' file from Active Directory (LADP) on users which contains 'phone' attribute
#
# Using:
# 1. Print users to STDOUT:
# users.pl
#
# 2. Print users to file:
# users.pl users_custom.conf
use strict;
use warnings;
use Net::LDAP;
use Lingua::Translit;
######################
### BEGIN SETTINGS ###
######################
my $debug = 0;
my $warning = 0;
# name of Domain
my $AD="steepler.local";
# Domain name in format AD
# for example  mydomain.ru
my $ADDC="DC=steepler,DC=local";
# user in Active directory
# example: "CN=asterisk,CN=Users,$ADDC"
my $ADUserBind="cn=openfire, cn=users, dc=steepler, dc=local";
my $ADpass="XXXXXXX";
# base search tree
# example "OU=Users,$ADDC"
my $ADUsersSearchBase="$ADDC";
# Field in active directory where telephone number, display name, phone stored
# "telephonenumber", "displayname", "mail"
my $ADfieldTelephone="telephonenumber";
my $ADfieldFullName="displayname";
my $ADfieldMail="mail";
my $ADfieldUser="samaccountname";
my $ADfieldGroup="memberOf";
my $ADSearchGroup="CN=IM,CN=Users,DC=steepler,DC=local";
# You need to create a dialplan in your asterisk server;
my $dialplan="office";
# default settings
my $user_static =
"context = $dialplan
call-limit = 100
type = friend
registersip = no
host = dynamic
callgroup = 1
threewaycalling = no
hasdirectory = no
callwaiting = no
hasmanager = no
hasagent = no
hassip = yes
hasiax = yes
nat=yes
qualify=yes
dtmfmode = rfc2833
insecure = no
pickupgroup = 1
autoprov = no
label =
macaddress =
linenumber = 1
LINEKEYS = 1
callcounter = yes
disallow = all
allow = ulaw,alaw,iLBC,h263,h263p
";
#######################
### END OF SETTINGS ###
#######################
my $ldap;
# get array DNS names of AD controllers
my $dig = "dig -t srv _ldap._tcp.$AD" . '| grep -v "^;\|^$" | grep SRV | awk "{print \$8}"';
my @adControllers = `$dig`;
# try connect to AD controllers
foreach my $controller (@adControllers){
    $controller =~ s/\n//;
    #INITIALIZING
    $ldap = Net::LDAP->new ( $controller ) or next;
    print STDERR "Connected to AD controller: $controller\n" if $debug > 0;
    last;
}
die "$@" unless $ldap;
my $mesg = $ldap->bind ( dn=>$ADUserBind, password =>$ADpass);
#PROCESSING - Displaying SEARCH Results
# Accessing the data as if in a structure
#  i.e. Using the "as_struct"  method
my $ldapUsers = LDAPsearch (
    $ADUsersSearchBase,
    "$ADfieldGroup=$ADSearchGroup",
    [ $ADfieldFullName, $ADfieldTelephone, $ADfieldMail, $ADfieldUser ]
)->as_struct;
# translit RUS module.
# GOST 7.79 RUS, reversible, GOST 7.79:2000 (table B), Cyrillic to Latin, Russian
my $tr = new Lingua::Translit("GOST 7.79 RUS");
my %hashPhones = ();
my $phones = \%hashPhones;
my @out;
while ( my ($distinguishedName, $attrs) = each(%$ldapUsers) ) {
    # if not exist phone or name - skipping
    my $attrPhone = $attrs->{ "$ADfieldTelephone" } || next;
    my $attrUser = $attrs->{ "$ADfieldUser" } || next;
    my $attrName = $attrs->{ "$ADfieldFullName" } || next;
    my $encName = $tr->translit("@$attrName");
    my $attrMail = $attrs->{ "$ADfieldMail" } || [""];
    # check for duplicates phone number
    if ( $phones -> {"@$attrPhone"} ){
        my $currUser = "@$attrName";
        my $existUser = $phones -> {"@$attrPhone"};
        print STDERR "@$attrPhone alredy exist! Exist:'$existUser' Current:'$currUser'... skipping - '[@$attrPhone] $currUser'\n" if $warning;
        next;
    } else {
        $phones -> {"@$attrPhone"} = "@$attrName";
    }
    # password for SID = (telephonenumber without first digit) + 1
    # example: phone=6232 pass=233
    #$phsecret =sprintf("%03d",( substr("@$attrVal",1,100)+1));
    my $phsecret = "@$attrPhone";
    my $lcuser = "@$attrUser";
    $lcuser = lc($lcuser);
    push (@out,
        "@$attrPhone "
        . "$lcuser "
        . "$encName\n"
    );
}       # End of that DN
# print to file
if (@ARGV){
    open FILE, "> $ARGV[0]" or die "Error create file '$ARGV[0]': $!";
    print STDOUT "Printing to file '$ARGV[0]'";
    print FILE @out;
    close FILE;
    print STDOUT " ...done!\n";
}
# print to STDOUT
else{
    print @out;
}
exit 0;
#OPERATION - Generating a SEARCH
#$base, $searchString, $attrsArray
sub LDAPsearch
{
    my ($base, $searchString, $attrs) = @_;
    my $ret = $ldap->search ( base    => $base,
                              scope   => "sub",
                                  filter  => $searchString,
                              attrs   => $attrs
                                );
    LDAPerror("LDAPsearch", $ret) && die if( $ret->code );
    return $ret;
}
sub LDAPerror
{
    my ($from, $mesg) = @_;
    my $err = "[$from] - error"
        ."\nCode: " . $mesg->code
        ."\nError: " . $mesg->error . " (" . $mesg->error_name . ")"
        ."\nDescripton: " . $mesg->error_desc . ". " . $mesg->error_text;
    print STDERR $err if $warning;
}

And here’s the second one on the bash:
phone-bindings-update-from-AD.sh :

#!/bin/bash
TIMESTAMP=`/bin/date +%d%m%y%k%M%S`
BACKUPDIR=/opt/openfire/bin/phone-mappings/backup
BINDIR=/opt/openfire/bin
WORKDIR=$BINDIR/phone-mappings
SCRIPTNAMEDEVICE=$WORKDIR/phone-bindings-from-AD-device.sql
SCRIPTNAMEUSER=$WORKDIR/phone-bindings-from-AD-user.sql
SCRIPT=$WORKDIR/$SCRIPTNAME
PERLSCRIPT=$BINDIR/users-from-AD.pl
DEVICETPLHEAD=$WORKDIR/phoneDevice.tplhead
DEVICEINJ=$WORKDIR/phoneDevice.inj
DEVICETPLFOOT=$WORKDIR/phoneDevice.tplfoot
USERTPLHEAD=$WORKDIR/phoneUser.tplhead
USERINJ=$WORKDIR/phoneUser.inj
USERTPLFOOT=$WORKDIR/phoneUser.tplfoot
#backuping tables
mysqldump -uXXXXXXX -pXXXXXXX openfire phoneDevice > $BACKUPDIR/phoneDevice-$TIMESTAMP.sql
mysqldump -uXXXXXXX -XXXXXXX openfire phoneUser > $BACKUPDIR/phoneUser-$TIMESTAMP.sql
# Clearing injections
cat /dev/null > $DEVICEINJ
cat /dev/null > $USERINJ
# finding current Asterisk server ID in openfire DB
serverID=`mysql -Bse "SELECT serverID  FROM openfire.phoneServer;" -uXXXX -pXXXX`
# resetting counters
counter=0
counter2=0
#executing perl script to retrieve current phone numbers from AD
for i in `$PERLSCRIPT`; do
    counter=`expr $counter + 1`
    binder[$counter]=$i
done
maxcount=$counter
counter=1
while [ "$counter" -lt "$maxcount" ]
do
#  deviding array into two with extensions and jids
    counter2=`expr $counter2 + 1`
    extension=${binder[$counter]}
    counter=`expr $counter + 1`
    username=${binder[$counter]}
    counter=`expr $counter + 1`
    callerID=${binder[$counter]}
    counter=`expr $counter + 1`
    callerID=$callerID\ ${binder[$counter]}
    counter=`expr $counter + 1`
    deviceID=$counter2
    userID=$counter2
# Creating phoneDevice injection
    echo INSERT INTO \`phoneDevice\` VALUES\($deviceID,\'SIP/$extension\',\'$extension\',\'$callerID\',1,$userID,$serverID\)\; >> $DEVICEINJ
# Creating phoneUser injection
    echo INSERT INTO \`phoneUser\` VALUES\($userID,\'$username\'\)\; >> $USERINJ
done
# Compile complete injections
cat $DEVICETPLHEAD > $SCRIPTNAMEDEVICE
cat $DEVICEINJ >> $SCRIPTNAMEDEVICE
cat $DEVICETPLFOOT >> $SCRIPTNAMEDEVICE
# Compile complete injections
cat $USERTPLHEAD > $SCRIPTNAMEUSER
cat $USERINJ >> $SCRIPTNAMEUSER
cat $USERTPLFOOT >> $SCRIPTNAMEUSER
# Injecting into tables
cat $SCRIPTNAMEDEVICE | mysql -uXXXXXXX -pXXXXXXX
cat $SCRIPTNAMEUSER | mysql -uXXXXXXX –pXXXXXXX

As you can see, the second script uses templates for the header and footer of the injection. Templates are obtained by executing mysqldump to existing tables and then trimming the result. Actually, here are the templates:

phoneUser.tplhead:

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
USE openfire;
DROP TABLE IF EXISTS `phoneUser`;
SET @saved_cs_client     = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE phoneUser (
userID bigint not null,
username varchar(255) not null unique,
primary key (userID)
);
SET character_set_client = @saved_cs_client;
LOCK TABLES `phoneUser` WRITE;
/*!40000 ALTER TABLE `phoneUser` DISABLE KEYS */;


phoneUser.tplfoot:
/*!40000 ALTER TABLE `phoneUser` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;


phoneDevice.tplhead:

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
USE openfire;
DROP TABLE IF EXISTS `phoneDevice`;
SET @saved_cs_client     = @@character_set_client;
SET character_set_client = utf8;
CREATE TABLE `phoneDevice` (
  `deviceID` bigint(20) NOT NULL,
  `device` varchar(255) NOT NULL,
  `extension` varchar(255) NOT NULL,
  `callerId` varchar(255) default NULL,
  `isPrimary` int(11) NOT NULL,
  `userID` bigint(20) default NULL,
  `serverID` bigint(20) NOT NULL,
  PRIMARY KEY  (`deviceID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
SET character_set_client = @saved_cs_client;
LOCK TABLES `phoneDevice` WRITE;
/*!40000 ALTER TABLE `phoneDevice` DISABLE KEYS */;


phoneDevice.tplfoot:

/*!40000 ALTER TABLE `phoneDevice` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;


We push the script into the crowns, execute and find the appeared user binding to the phones in the Phone Bindings tab of the Asterisk-IM plugin. Half the job done.

The next task is to send missed call messages. If you have TrixBox or FreePBX - do as I do - everything will probably work. If naked Asterisk - everything is in your hands, improvise, a lot is available to you. I even partially envy)))

First you need to perform authorization via ssh with the keys - we will use scp and remote procedure execution. ssh-keygen will help you, there are enough manuals on the network, I won’t repeat myself. The script on the jabber server will climb into the database that we edited with the previous script (yes, they can be combined into one, but I didn’t solve the tasks at the same time, and in general - the unix way says that the tasks are divided into components correctly), take out the user login , phone number. Generate jID. Next, we prepare an executable script that will enter information into the Asterisk built-in database, transfer it to the Asterisk server and run it.

Here's what happened:
phone-mapping-request.sh :
#!/bin/bash
WORKDIR=/opt/openfire/bin/phone-mappings
SCRIPTNAME=phone-mappings-script.sh
SCRIPT=$WORKDIR/$SCRIPTNAME
SERVER=jbrgseveren01.steepler.local
#asterisk USER@HOST:/PathToFile
ASTERISK=root@10.10.8.98
#asterisk /PathToFile
RPATH=/etc/asterisk/scripts
counter=0
counter2=0
#clearing script file
cat /dev/null > $SCRIPT
#perform MYSQL request for mappings
for i in `mysql -Bse "SELECT extension,username  FROM openfire.phoneDevice JOIN openfire.phoneUser ON openfire.phoneUser.UserID=openfire.phoneDevice.UserID;" -uXXXX -pXXXX`; do
    counter=`expr $counter + 1`
    mapper[$counter]=$i
done
maxcount=$counter
counter=1
while [ "$counter" -lt "$maxcount" ]
do
#  deviding array into two with extensions and jids
    counter2=`expr $counter2 + 1`
    extension[$counter2]=${mapper[$counter]}
    counter=`expr $counter + 1`
    jid[$counter2]=${mapper[$counter]}
    counter=`expr $counter + 1`
# forming asterisk script
    outstringdel="asterisk -rvx \"database del AMPUSER "${extension[$counter2]}"/jid\""
    outstringadd="asterisk -rvx \"database put AMPUSER "${extension[$counter2]}"/jid "${jid[$counter2]}"@"$SERVER"\""
    echo $outstringdel >> $SCRIPT
    echo $outstringadd >> $SCRIPT
done
# moving scrip to asterisk host
chmod 755 $SCRIPT
scp $SCRIPT $ASTERISK:$RPATH
# run script
ssh $ASTERISK $RPATH/$SCRIPTNAME


The small thing is to explain to Asterisk what to do with it. Here a huge amount of time was spent finding an entry point. If it works like mine - fine. If not, I give a tip. An asterisk, if different instructions are included for the same condition (that is, one action on the condition is written in the dialplan, and another is included in the inclusion from the loaded context), it takes for the instruction the one that was received first. Subsequent stupidly ignored. I mean, if you wrote some function, inserted it, and the result is zero, make a dialplan show and see where this condition in this context branch occurs with all include before yours.
In my case, it turned out to be sufficient to add to extensions_custom.conf :

[from-internal-noxfer-custom]
; Missed calls Jabber notification
exten => h,1,Macro(XMPPSend,)
exten => h,n,Macro(hangupcall)
[macro-XMPPSend]
; Missed calls Jabber notification
exten => s,1,GotoIf($["foo${DB(AMPUSER/${THISDIAL:4}/jid)}" = "foo"]?5:2)
exten => s,n,Set(JID=${DB(AMPUSER/${THISDIAL:4}/jid)})
exten => s,n,Jabbersend(asterisk-jabber,${JID},${STRFTIME(${EPOCH},,%d/%m/%Y-%H:%M:%S)} - Пропущенный вызов на номер ${THISDIAL:4} от ${CALLERID(name)}, номер ${CALLERID(num)})
exten => s,n,MacroExit()
exten => s,n,Noop(No Jabber ID provided for target extension - ${THISDIAL:4})
exten => s,n,MacroExit()


And, register Asterisk as a component of OpenFire:
On the Asterisk side:
Jabber.conf:
[general]
debug=no                              ;;Turn on debugging by default.
;autoprune=yes                          ;;Auto remove users from buddy list.
;autoregister=yes                       ;;Auto register users from buddy list.
[asterisk-jabber]                          ;;label
type=component                             ;;Client or Component connection
serverhost=jbrgseveren01.steepler.local                     ;;Route to server
username=asterisk                        ;;Username with optional roster.
secret=XXXX                       ;;Password
port=5275                               ;;Port to use defaults to 5222


On the OpenFire side, go to Server -> Server Settings -> External Components Settings
Enable Service Enabled. If desired, add asterisk to whitelist.

Checking the service ...

I hope something helped. If you have questions - write.

Also popular now: