Wednesday, May 29, 2013


Linksys SPA Provisioning или облегчаем себе жизнь при массовой настройке IP-телефонов.

Предисловие


После недавнего «падения» сервера с Asterisk и его восстановления в логах обнаружил тысячи вот таких строк:
....
[Apr 5 22:28:15] NOTICE[1170] chan_sip.c: Registration from '"10/1/65"<sip:10/1/65@95.160.34.175>' failed for '184.82.7.52' - No matching peer found
[Apr 5 22:28:15] NOTICE[1170] chan_sip.c: Registration from '"11/1/65"<sip:11/1/65@95.160.34.175>' failed for '184.82.7.52' - No matching peer found
[Apr 5 22:28:15] NOTICE[1170] chan_sip.c: Registration from '"1346"<sip:1346@95.160.34.175>' failed for '184.82.7.52' - No matching peer found
[Apr 5 22:28:15] NOTICE[1170] chan_sip.c: Registration from '"1347"<sip:1347@95.160.34.175>' failed for '184.82.7.52' - No matching peer found
....

В секунду ~70 запросов с «левых» ip-адресов. Явный брутфорс стал для меня неприятным сюрпризом, который заставил задуматься о смене простых паролей для sip-клиентов на более сложные. Смена пароля в конфигах Asteriska дело нескольких минут, смена пароля в web-интерфейсе ip-телефона Linksys SPA922 — минута. Но когда этих телефонов около сотни это становится проблемой.

После недолгого гугления нашел информацию о Linksys SPA Provisioning. Что нам это дает? По умолчанию ip-телефоны, поддерживающие provisioning, при загрузке ищут в сети tftp-сервер с конфигурационными файлами вида spa$PSN.cfg и spa$MA.cfg, где $PSN — это модель (в моем случае $PSN=922), а $MA — MAC-адрес телефона. Файл spa$PSN.cfg может содержать как общий конфиг телефона, так и включать пути к другим файлам с конфигурацией. Файл spa$MA.cfg содержит индивидуальную данные телефона, как правило это логин/пароль. Это именно то, что нам нужно для массовой смены паролей. Приступим.

Настройка


ОС — Ubuntu 10.04 Server.

Устанавливаем tftp-сервер:

$ sudo apt-get install atftp atftpd

Правим настройки:

$ sudo mcedit /etc/default/atftpd
USE_INETD=true
OPTIONS="--tftpd-timeout 300 --retry-timeout 5 --mcast-port 1758 --mcast-addr 239.239.239.0-255 --mcast-ttl 1 --maxthread 100 --verbose=5 /srv/tftp"


меняем на

USE_INETD=false
OPTIONS="--daemon --tftpd-timeout 300 --retry-timeout 5 --mcast-port 1758 --mcast-addr 239.239.239.0-255 --mcast-ttl 1 --maxthread 100 --verbose=5 --logfile=/var/log/atftp.log /var/tftp"


Выполняем команду:

$ sudo invoke-rc.d atftpd start

Создаем папку и меняем права:

$ sudo mkdir /var/tftp
$ sudo chmod -R 777 /var/tftp
$ sudo chown -R nobody /var/tftp


Создаем файл для ведения логов:

$ sudo touch /var/log/atftp.log

Перезапускаем tftp-сервер:

$ sudo /etc/init.d/atftpd restart

Примечание: у меня после этого сервер не запустился, в логах увидел ошибку atftpd: can't bind port :69/udp.
69 порт, по-умолчанию используемый tftp, занят.
Освободим его:

$ sudo /etc/init.d/openbsd-inetd stop
$ sudo invoke-rc.d atftpd restart


Проверяем:

$ ps -e | grep atftp
886 ? 00:00:02 atftpd


Настраиваем DHCP-сервер, всего лишь добавляем строчку:

$ sudo mcedit /etc/dhcp3/dhcpd.conf
....
subnet 192.168.0.0 netmask 255.255.255.0 {
....
option tftp-server-name "192.168.1.200";
....;
}


Перезапускаем:

$ sudo /etc/init.d/dhcpd restart

Создаем главный конфигурационный файл с таким содержимым:

$ sudo mcedit /var/tftp/sip922.cfg
<flat-profile>
<Profile_Rule ua="na">/linksys/spa.cfg</Profile_Rule>
<Profile_Rule_B ua="na">/linksys/spa$MA.cfg</Profile_Rule_B>
<Resync_Periodic ua="na">30</Resync_Periodic>
</flat-profile>


Создаем папку для всех остальных файлов:

$ sudo mkdir /var/tftp/linksys
$ sudo chmod -R 777 /var/tftp/linksys
$ sudo chown -R nobody /var/tftp/linksys


Раз уж делаем глобальное обновление, то скачаем заодно и новую прошивку для телефонов:

$ cd /var/tftp/linksys
$ wget download.cisco.com/swc/esd/03/282414121/anon/SPA942_6.1.5a.zip
$ 7z x SPA942_6.1.5a.zip


Создаем конфигурационный файл c глобальными настройками для ip-телефонов:

$ sudo mcedit /var/tftp/linksys/spa4all.cfg
<flat-profile>
<Upgrade_Rule>/linksys/spa942-6-1-5a.bin</Upgrade_Rule>
<Upgrade_Enable>Yes</Upgrade_Enable>
<Resync_Periodic ua="na">3600</Resync_Periodic>
<Voice_Mail_Number ua="na">8500#</Voice_Mail_Number>
<Primary_NTP_Server ua="na">time.etg.local</Primary_NTP_Server>
<Time_Zone ua="na">GMT+04:00</Time_Zone>
<Time_Format ua="na">24hr</Time_Format>
<Date_Format ua="na">day/month</Date_Format>
<Select_Logo ua="na">None</Select_Logo>
<Select_Background_Picture ua="na">None</Select_Background_Picture>
<BMP_Picture_Download_URL ua="na"></BMP_Picture_Download_URL>
<Text_Logo ua="na">ETech</Text_Logo>
<Screen_Saver_Enable ua="na">No</Screen_Saver_Enable>
<Screen_Saver_Wait ua="na">300</Screen_Saver_Wait>
<Screen_Saver_Icon ua="na">Phone</Screen_Saver_Icon>
</flat-profile>


Для создания файлов с индивидуальными для каждого телефона настройками я воспользовался скриптом, найденным на просторах интернета. Спасибо автору этой статьи. Скрипт немного переделал под себя:

$ cat /var/tftp/createprov.sh
#!/bin/bash

first=flat-profile
second=GPP_A
third=Display_Name_1_
forth=User_ID_1_
fifth=Password_1_
sixth=Proxy_1_
general='ua="na"'

#Sample File to parse
#IpAddress Mac_Address Sip Server Last First Name Username Password
#192.168.4.1 00065B8C1E2C 192.168.4.1 Tsakalos Stratis 314 314
#192.168.4.5 00065B8C1E2D 192.168.4.1 Test User 255 255

while read line

do
input[$i]=$line;
i=$(( $i + 1 ))

ip_address=`echo $line|cut -d';' -f1`
mac_address=`echo $line|cut -d';' -f2 | tr "[:upper:]" "[:lower:]"`
proxy=`echo $line|cut -d';' -f3`
display=`echo $line|cut -d';' -f4`
number=`echo $line|cut -d';' -f5`
password=`echo $line|cut -d';' -f6`

echo "<$first>" > linksys/spa$mac_address.cfg
echo "<$second>$ip_address</$second>" >> linksys/spa$mac_address.cfg
echo "<$sixth $general>$proxy</$seventh>" >> linksys/spa$mac_address.cfg
echo "<$third $general>$display</$forth>" >> linksys/spa$mac_address.cfg
echo "<$forth $general>$number</$fifth>" >> linksys/spa$mac_address.cfg
echo "<$fifth $general>$password</$sixth>" >> linksys/spa$mac_address.cfg
echo "</$first>" >> linksys/spa$mac_address.cfg
done < sipusers.csv


Этот скрипт берет данные из файла sipusers.csv и создает конфиги вида spa000e08de401a.cfg для каждого телефона.
Теперь необходимо собрать MAC-адреса телефонов с привязкой к номеру.
Делаем скрипт исполняемым:

$ chmod +x /var/tftp/createprov.sh

Конфигурацию телефона можно посмотреть по адресу phone_ip_address/admin/spacfg.xml. Там можно увидеть и MAC-адрес и номер телефона, но бегать по айпишникам очень скучно, поэтому запустим пару команд:

$ cd /var/tftp/linksys/
$ wget --tries=1 192.168.0.{1..254}/admin/spacfg.xml


Этой командой мы скачали конфиги всех зарегистрированных в сети телефонов.
Получился список файлов:

$ ls -l /var/tftp/linksys/
итого 1268
-rw-r--r-- 1 nobody nogroup 780 2011-04-14 14:12 spa4all.cfg
-rw-r--r-- 1 root root 248 2011-04-13 18:32 spa000e08de401a.cfg
-rw-r--r-- 1 root root 250 2011-04-13 18:32 spa000e08de401b.cfg
-rw-r--r-- 1 root root 236 2011-04-13 18:32 spa000e08de401c.cfg
-rw-r--r-- 1 root root 244 2011-04-13 18:32 spa000e08de401d.cfg
-rw-r--r-- 1 root root 244 2011-04-13 18:32 spa000e08de401e.cfg
....


$ egrep 'MAC_Address|<User_ID_1' spacfg.xml* >> MAC.txt

Этой командой сделали выборку по MAC-адресу и номеру телефона:

$ cat /var/tftp/linksys/MAC
spacfg.xml:<MAC_Address group="Info/Product_Information">000E08DE401A</MAC_Address>
spacfg.xml:<User_ID_1_ group="Ext_1/Subscriber_Information">101</User_ID_1_>
spacfg.xml.1:<MAC_Address group="Info/Product_Information">000E08DE401B</MAC_Address>
spacfg.xml.1:<User_ID_1_ group="Ext_1/Subscriber_Information">102</User_ID_1_>
spacfg.xml.10:<MAC_Address group="Info/Product_Information">000E08DE401C</MAC_Address>
spacfg.xml.10:<User_ID_1_ group="Ext_1/Subscriber_Information">103</User_ID_1_>
spacfg.xml.11:<MAC_Address group="Info/Product_Information">000E08DE401D</MAC_Address>
spacfg.xml.11:<User_ID_1_ group="Ext_1/Subscriber_Information">104</User_ID_1_>
spacfg.xml.12:<MAC_Address group="Info/Product_Information">000E08DE4001E</MAC_Address>
....


После нехитрых манипуляций в LibreOffice Calc файл MAC.txt привели к такому виду (создали новый файл sipusers.csv):

$ cat /var/tftp/sipusers.csv
192.168.1.200;000e08de401a;192.168.1.200;Maksim Petrov;101;CJIO}I{HbIu'napoJIb
192.168.1.200;000e08de401b;192.168.1.200;Nikolay Veselov;102;CJIO}I{HbIu'napoJIb
192.168.1.200;000e08de401c;192.168.1.200;Galina Fedorova;103;CJIO}I{HbIu'napoJIb
192.168.1.200;000e08de401d;192.168.1.200;Ludmila Sokolova;104;CJIO}I{HbIu'napoJIb
192.168.1.200;000e08de401e;192.168.1.200;Chiya Chiyo;105;CJI0}I{HbIu'napoJIb
....


Что есть что понятно из примечания в скрипте createprov.sh:
#Sample File to parse
#IpAddress Mac_Address Sip Server Last First Name Username Password
#192.168.4.1 00065B8C1E2C 192.168.4.1 Tsakalos Stratis 314 314
#192.168.4.5 00065B8C1E2D 192.168.4.1 Test User 255 255


Запускаем createprov.sh на выполнение:

$ ./createprov.sh

Смотрим результат:

$ ls -l /var/tftp/
итого 20
-rwxr-xr-x 1 nobody nogroup 1413 2011-04-13 18:32 createprov.sh
drwxrwxrwx 3 nobody nogroup 4096 2011-04-14 14:12 linksys
-rw-r--r-- 1 root root 5454 2011-04-13 18:04 sipusers.csv
-rw-r--r-- 1 nobody nogroup 240 2011-04-13 10:50 spa922.cfg

$ ls -l /var/tftp/linksys/
итого 1268
-rwxrwxrwx 1 nobody nogroup 814 2010-01-15 10:47 logo.bmp
-rw-r--r-- 1 nobody nogroup 780 2011-04-14 14:12 spa4all.cfg
-rw-r--r-- 1 root root 12835 2011-04-13 17:18 MAC.txt
-rw-r--r-- 1 root root 248 2011-04-13 18:32 spa000e08de401a.cfg
-rw-r--r-- 1 root root 250 2011-04-13 18:32 spa000e08de401b.cfg
-rw-r--r-- 1 root root 236 2011-04-13 18:32 spa000e08de401c.cfg
-rw-r--r-- 1 root root 244 2011-04-13 18:32 spa000e08de401d.cfg
-rw-r--r-- 1 root root 244 2011-04-13 18:32 spa000e08de401e.cfg
....

Wednesday, May 22, 2013

Event ID error messages 10016 and 10017 are logged in the System log SharePoint 2010


Event ID error messages 10016 and 10017 are logged in the System log after you install Windows SharePoint Services 3.0

You install Microsoft Windows SharePoint Services 3.0. When you view the System log after Windows SharePoint Services 3.0 is successfully installed, you see the following event ID error message logged one or more times:
Type: Error
Source: DCOM
Category: None
Event ID: eventID
Description:
The application-specific permissions settings do not grant Local Activation permission for the COM Server application with CLSID {CLSID} to the user DomainName\UserName SID {SID}. This security permission can be modified using the Component Services administration tool.
Note In this event ID error message, eventID is a placeholder for event ID 10016 or event ID 10017.
This issue occurs if the domain user account that you specified as the Windows SharePoint Services 3.0 service account does not have the Local Activation permission to the IIS Wamreg Admin Service. The event ID error messages 10016 or 10017 that are mentioned in the "Symptoms" section do not affect the functionality of Windows SharePoint Services 3.0.
You can safely ignore the event ID error messages 10017 or 10016 that are logged in the System log. If you want to prevent the event ID error messages from being logged in the System log, use the Component Services snap-in to enable the Local Activation permission to the IIS Wamreg Admin Service for the domain user account that you specified as the Windows SharePoint Services 3.0 service account. To do this, follow these steps:
  1. Click Start, click Run, type dcomcnfg in the Open box, and then click OK.
  2. Expand Component Services, expand Computers, expand My Computer, and then click DCOM Config.
  3. Right-click IIS WAMREG admin Service, and then click Properties.
  4. Click the Security tab.
  5. Under Launch and Activation Permissions, click Edit.
  6. In the Launch Permission dialog box, click Add.
  7. In the Select Users, Computers, or Groups dialog box, change the location to the local server. Then, type the local security group WSS_WPG, click Check Names, and then click OK.
  8. In the Permissions for UserName list, click to select the Allow check box that is next to Local Activation, and then clickOK two times.   
1. Run Regedit.exe and browse to "HKEY_CLASSES_ROOT\AppID\{61738644-F196-11D0-9953-00C04FD919C1}" key.
2. Secondary-mouse click on the {61738644-F196-11D0-9953-00C04FD919C1} key and select Permissions...
3. Click the Advanced button in the Permissions window and select the Owner tab. Under Change owner to select the local Administrators group and click on Apply, thenOK.
4. Then under Permissions window, select the local Administrators group and under Permissions for Administrators select Full Control and click on Apply, then OK.
NOTE: DO NOT modify/change any permissions for the TrustedInstaller account.

5. Re-run the Component Services management console (dcomcnfg.exe) and you should now be able to modify the settings for IIS WAMREG admin service package.
7.Use the following steps to grant the AX Business Connector Proxy User account the Launch and Activation rights
a.Expand Component Services, expand Computers, expand My Computer, and expand DCOM Config.
b.Right-click IIS WAMREG admin Service, and then click Properties.
c.Click the Security tab.
d.Under Launch and Activation Permissions, click Edit.
e.Under Group or user names section, add the Business Connector Proxy User account, and select the user account
f.Under Permissions for the Business Connector Proxy User account, select the Local Launch and Local Activation checkboxes
g.Click OK and OK and close the Component Services management console.


Enable Incoming emails on a Custom SharePoint List


We had a requirement recently whereby we needed to create a custom SharePoint list that would accept incoming emails. This post is going to be very long so bear with me …
Initially, I was very optimisitic that all I needed to do was to setup incoming notifications via Central Administration and then turn on Incoming Email notifications on the list itself and it should all fall into place.
How wrong I was!
Setting up the Development Enviornment
The first thing you have to do is to setup your development enviornment so that you can send emails and your SharePoint list can recieve them. This turned out to be a massive task. I spent hours searching through blogs, forums and various sites to try and setup the infrastructure on my dev (Hyper-v VM based) enviornment but I just could not get it to work. Eventually I stubmled upon this post from Marc Charmois that explained in detail how to get the whole thing to work on your Dev enriornment:
Enabling Incoming-emails on the SharePoint List. The Problem:
Ok, so I created a custom SharePoint List went to List Settings and looked for the ‘In-coming email settings’ link under the ‘Communication’ settings and found it to be non-existent. Googling on this brought all sorts of theories, hearsay and rumours to light. Some thought that this option was only available on x,y or z type of lists then there were others that thought it was only available on a,b,c or d type of lists but one thing was for sure no one seemed to know for a fact what was actually going on. As I was looking at the object model I found a property on the SPList object called ‘CanReceieveEmail’. I thought maybe this was the answer i.e. all I needed to do was to get my list and set this property to true and it will all work. However you cannot set this property you can only get its value. I believe this property is used by the SharePoint UI to decide whether or not to show the ‘In-coming Email Settings’ link in the list settings area.
So it was time to fire up Reflector to find a way to set this property maybe through reflection?
Looking at the property via reflection I found:
1
2
3
4
5
6
7
8
public bool get_CanReceiveEmail()
{
    if (!SPEmailHandler.HasHandler(this.BaseTemplate) && !this.HasExternalEmailHandler)
    {
        return false;
    }
    return !SPMeeting.IsMeetingWorkspaceWeb(this.ParentWeb);
}
And ..
1
2
3
4
5
6
7
8
public static bool HasHandler(SPListTemplateType templateType)
{
    if ((((templateType != SPListTemplateType.Announcements) && (templateType !=    SPListTemplateType.Events)) && ((templateType != SPListTemplateType.DocumentLibrary)  && (templateType != SPListTemplateType.PictureLibrary))) && ((templateType !=  SPListTemplateType.XMLForm) && (templateType != SPListTemplateType.DiscussionBoard)))
    {
        return (templateType == SPListTemplateType.Posts);
    }
    return true;
}
And finally ….
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
internal bool HasExternalEmailHandler
{
    get
    {
        bool flag = false;
        foreach (SPEventReceiverDefinition definition in this.EventReceivers)
        {
            if (definition.Type == SPEventReceiverType.EmailReceived)
            {
                flag = true;
            }
        }
        return flag;
    }
}
From this we can determine the following:
If the list, regardless of its type, appears in a meeting workspace web it will not be able to recieve in-coming emails.
The list either needs to have the BaseTemplate of one of the following:
  • Announcements
  • Events
  • DocumentLibrary
  • PictureLibrary
  • XMLForm
  • DiscussionBoard
  • Posts
or it needs to have an event handler of type ‘EmailReceived’ attached to it.
An important point to note here is that it mentions the base template which should not be mistaken for the BaseType. What this means is that you could create a custom list that inherits from the BaseType Document Library but that does not mean that it will have incoming emails enabled. Your list will need to have the same BaseTemplate as the out of the box lists mentioned above which is not really ideal.
Enabling Incoming-emails on the SharePoint List. The Solution:
So the only route left for me to take was to go the Event Handler path. I attached the Event Handler (and the incomming email settings link started to appear in the list settings area) then sent an email to my list and debugged my code with a break point on my event handler. However it just never seemed to get hit and neither were my emails appearing in the list itself.
The mistake I was making was to attach the w3wp process but this is not the process that processes the incoming emails. I dont want to go into this in detail but the incoming emails are processed by a SharePoint job that runs every minute therefore the process I needed to attach was the OWSTimer process. Once I attached this process it started to hit my break point however the emails were still not appearing in the list.
One thing to note here is that whenever you make any code changes to this event handler, after you deploy the dll’s to GAC, you need to ensure you restart the SharePoint Timer Job Service because it holds a cached version of the dll’s.
Finally, the reason the emails were not appearing in the list was because this needs to be done via the Event Handler. For the lists that are from one of the Templates I mentioned above SharePoint understands how to process and add the email messages however for your own custom list it is down to the Developer to write the code to do this processing. The event handler though provides you an object of type SPEmailMessage which has all the data you require. Below is an example of how it can be used to add the email subject to a simple custom list with only a title field:
1
2
3
4
5
6
public override void EmailReceived(SPList list, SPEmailMessage emailMessage, String receiverData)
{
    SPListItem newItem = list.Items.Add();
    newItem["Title"] = emailMessage.Headers["subject"]
    newItem.Update();
}
You can easily extend it to deal with attachments as well but that is for another day!
P.S Illustrations to be added soon….