Friday, November 22, 2013

Polycom VVX Normalization Rule Issue

Working on a customer system I came across an interesting issue. The Polycom VVX 5.0.1 firmware does not process Normalization rules with more than 1 group (i.e. $1 and $2). It can only process rules that have a single group (i.e. just $1).

Here is an example of a rule that will not process:

^(150)(\d{4})$
+1303555$2;ext=$1$2

Ideally you would like to have the flexibility of capturing multiple groups and being able to create complex normalization rules... but for now you are limited to doing something like this instead:

^150(\d{4})$
+1303555$1;ext=150$1

There are no errors in logs, or in Lync that indicate an issue. Just the inability of the phone to connect to the number you expect.

Update: Thanks to some feedback on comments below the problem has been narrowed down even further. It appears as if the error processing the rules kicks is when $2 is used multiple times. This is usually used when you have ;ext= formats like the above example.

This rule where each group is used once will process fine

^(150)(\d{4})$
+1303$1$2

This rule although silly will also process fine

^(150)(\d{4})(150)(\d{4})$
+1303$1$2;ext=$3$4

Feel free to comment down below if you find something else..

As always thanks for reading...

Tuesday, November 19, 2013

Windows Azure Active Directory Sync tool - Version Release History

Microsoft has started tracking release history for the new versions of Windows Azure Active Directory Sync tool since June 2013.

The following information is available:
  • Version number
  • Released Date
  • Changes/Fixes
Don't know what version you are running... the page provides that as well...

Enjoy!

https://social.technet.microsoft.com/wiki/contents/articles/18429.windows-azure-active-directory-sync-tool-version-release-history.aspx

Thursday, November 14, 2013

Using Wireshark to Decrypt Lync Communications

There is a sister blog post to this that shows how to decrypt HTTPS without using a private key. Some of the newer ciphers make this blog post impossible without removing them (Diffe Hellman for example and leaving RSA).


If you have never decrypted SSL/TLS using Wireshark... you have never really lived. There is nothing quite like being able to see exactly what is on the wire. Lync has some great debugging tools, but there are times, especially with web services, where I wish I could see more of what is being transmitted back and forth.

Now you are probably thinking this isn't anything special, I can do this with Fiddler.

Although Fiddler is a great tool, it doesn't work if you want to see what is happening with web services on Lync Phone Edition. It also doesn't work well if you want to see other packets along side the web services to correlate issues with STUN in Lync Web App. I would also argue that Fiddler became so popular because doing Wireshark decrypting in the past was not for the faint of heart and it got the job done. Good news is that when I recently checked on a new version of Wireshark, this process is immensely easier. Since I have a love for Wireshark already... I won't be using Fiddler any time soon.

This blog post aims to give you the tools necessary to see exactly what is on the wire, even when those packets are encrypted. Let's dig in...


Getting the Private Key
If you have ever installed OCS/Lync you are quite familiar with Certificates. I'm not going to go in to the detail of why and how certificates are used. You can read Wikipedia for that. Just know there is a key piece of information we need to do decryption in Wireshark and that little bit of goodness is a private key.

The private key is essentially the secret decoder ring that allows us to view what is in the packets as if they were not encrypted. So... how do you get the private key. That is quite easy as long as you have access to the server where it is stored.

Let me show you how...

Login in to the server where the private key is stored. This could be your reverse proxy or Lync Front End server. Which private key depends on where you client is and what servers they are communicating with.

Open up an instance of Microsoft Management Console (I prefer to just hit the run dialog box and type "mmc")



Next select Add/Remove Snap-in from the File Menu



Select Certificates and click "Add >"


Select "Computer account" and click "Next"


Make sure "Local computer" is selected and click "Finish"


You will notice a "Certificates (Local Computer)" displayed under Console Root. Click "OK".


Open up the Personal Certificate Store and Right-Click the certificate you would like to export (with the private key)


Look a wizard! Click "Next".


Select "Yes, export the private key" and click "Next".


Click "Next" (DO NOT select Delete the private key if the export is successful. It will ruin your day)


Give it a password you will remember and click "Next".
Keep in mind this password will be viewable in Wireshark so don't use you super secret passphrase


Give it a filename to store the certificate with private key. This should be a .pfx file.


Woohoo! Click "OK"


Now you should move the .pfx file to whatever machine will be running Wireshark.

Decrypting Packets in Wireshark
Don't have Wireshark yet? Get it here. You will want a fairly up to date version for what I'm about to show you. 1.8.x or later should be good. As of writing this blog the latest stable release is 1.10.3.

So if you have tried to decrypt packets in the past, you have no doubt become good friends with openssl and all the different commands to pull out the RSA key so that Wireshark could show you all that unencrypted goodness.

Guess what... no need to go through all that pain anymore. You can have your cake and eat it too!!

Wireshark will take the .pfx file straight out of your windows box and pull out the key for you... on the fly. Don't you just love it when software gets new features that is actually useful?

So here is how you configure Wireshark to decrypt SSL...

Fire up Wireshark and before you start a packet capture (you can do this after you have a capture too) select "Preferences" under the "Edit" menu


Behold... the Preferences Dialog


Open up the "Protocols" header and scroll down forever...


Click on "SSL" and then click on "Edit" next to "RSA keys list"


Click "New"


Put in the IP address for the server you are communicating with (example: Reverse Proxy or Front End).

Then specify the port the traffic is communicating on (443 for https).

Next, what protocol you are expecting after the packets are decrypted (http in this example).

Select your .pfx file and finally type in the password you entered when creating the file.



If you didn't fat finger something you should get a RSA key list that looks like this.


Next you need to enter in a SSL debug file. When done click "OK".



Now you are ready to do a packet capture. One key thing to remember when decrypting SSL is that it does no good to start in the middle of a packet conversation.

You need to capture the initial key exchange otherwise you will get nothing.

Sometimes this requires a reboot because the client machine will cache SSL keys and won't do a full key exchange.

Here is an example of capture I did for Lync Web App


Here is the packet detail all laid out nicely for us


Here is the packet byte section


 Notice down at the bottom you have several tabs. This indicates the original encrypted data in the "Frame" tab. Then the important bit is the "Reassembled SSL" tab which shows the complete data unencrypted and reassembled from multiple packets.


Not just for HTTP
Now you are probably thinking to yourself... if I can do this for https and technically Lync uses SSL/TLS for SIP... then I should be able to decrypt SIP as well... and you would be right.

Technically Wireshark can do this for sip.tcp, http. smtp, ldap, imap, pop, q931.tpkt (not sure about that one) and skinny.

Just go through the same process and instead of using port 443 and http for your protocol on the RSA key list, specify port 5061 and "sip" protocol.

Getting a good capture of SIP with Lync is a bit more tricky because you need to wait for a key exchange to happen. This can prove to be frustrating and most people just prefer to capture the SIP the old fashioned way using the Lync debugging tools. Which I agree with most of the time.

But there are a couple of instances where this technique can be handy.
  1. Capturing sip and/or http traffic (ever have EWS yellow triangle) from Lync Phone Edition devices which have notoriously hard to read logs.
  2. Capturing SIP traffic going through a Load Balancer (I know that is sooooo OCS 2007). Why? Because by the time it goes through the load balancer you can't figure out what the original endpoint was. Having view of the SIP packet details can help you troubleshoot connections where the Load Balancer might be the problem.
Feel free to make comments below on other ways to use this...

Want more Wireshark check out my other blog... http://blog.lyncdialog.com/2010/10/wireshark-tips-and-tricks-for-voipsip.html

Also check out a blog written by Matt Landis that also covers some quirks you might encounter... http://windowspbx.blogspot.com/2013/11/getting-started-with-lync-and-wireshark.html?utm_source=twitterfeed&utm_medium=twitter









Wednesday, November 6, 2013

Tips and Tricks for using Microsoft Lync

I've been doing teleworking since 1998 and Unified Communications since 2003 (Nortel Succession MX). Using Unified Communications has become second nature to me and it occurred to me the other day that some of the techniques I use might not be obvious to others just starting out. My goal with this blog post is to share some of these techniques and make the way you use Microsoft Lync more effective.

Alternative Communication Methods
When I started using AOL Instant Messenger back in 1999 for business communication, it was out of necessity. My hiring manager at Nortel worked in Hartford, CT, and I lived in Lakewood, CO. I couldn't simply walk in to his office and get his attention or pass him a note. I also didn't have the luxury of presence to let me know he was on the phone or in a meeting. So I was left with the option to call him when I had an urgent matter that needed his attention. As you might expect... Being a busy person I hit his voicemail most of the time and this killed my productivity.

I tried an experiment with him and had my manager install AOL Instant Messenger so we could communicate while he was on the phone. As an added benefit, I also knew when he was at his computer because of his presence. It worked so well that within a few days he required the whole Services organization under him to get AOL Instant Messenger accounts so they could communicate with him and each other in the same way.

Another benefit was that any messages he missed while he was out, were immediately visible when he returned. No need to go through voicemail to find out what the critical issues were.

This same scenario can be applied to Microsoft Lync or any other decent Unified Communications system for that matter. The lesson learned was that when you have alternative communication methods available you can still communicate and get critical decisions or information that keeps business flowing. Because decisions can be made in real time and productivity is increased dramatically.

Out of Band Communications
Another technique I discovered fairly quickly was what I call out of band communications. "Out of Band" is a technical term that is defined as transmission of data or information by not using the already established primary communications channel.

An example for Microsoft Lync would be the need for two parties on a conference call to communicate information without others on the conference call knowing. This information can be shared "out of band" through alternative communications.

To illustrate further, an Engineer could have the need to share a critical piece of information to a Project Manager just before an incorrect statement is made to a customer. Instead of interrupting the conversation and making the Project Manager look less prepared, now the Project Manager has the correct information to give the customer just in time.

To accomplish this scenario, Instant Messaging can be used to send that information out of band without the other parties on the conference call knowing. As a side note, you might want to turn down your computer sound or mute the mic on your phone because the constant ding, ding, ding of Instant Messages could have a negative effect as well.

Taking the concept a bit further, Instant Message Conferencing can also be used if there are more than two parties that have the need to communicate out of band. This will allow the whole team to be on the same page and share information in real time during a conference call. Throw in Lync Federation and now you can bring in a partner organization to the same Instant Message Conference and keep the whole team that is delivering the solution on the same page.

Another take on the scenario would be requesting information from a third party that is not on the conference call, but has critical information that would benefit the parties on the conference call. You can go down through your contact list or use Lync Skill Search to find an appropriate resource and then reach out to them using an Instant Message. Maybe after a few Instant Messages, you get to the point where you feel the third party should be part of the conversation on the conference call. With Microsoft Lync, they are a quick click and drag away from joining the conference call.

SIP URI vs Phone Number
I became familiar with the notion of a SIP URI (Uniform Resource Identifier) when I started using Nortel Succession MX. It did not take long before I realized I could reach someone by calling someone@domain.com (SIP URI) versus a Phone number and soon started to use the SIP URI primarily.

Being able to call a person by their SIP URI meant the good old company directory wasn't as important because now I had an easy way of telling my computer of who I wanted to communicate with.

What is great about Microsoft Lync is that the system does not care whether a call is by SIP URI or Phone Number. The Microsoft Lync will do a Reverse Number Lookup if a Phone Number is entered and map to the SIP URI of the user so that other modalities like Instant Message or Collaboration can be escalated to.

Think about this another way... what about when you start with an Instant Message to someone and then want to escalate other types of communications like Audio or Video. Now that Phone Number isn't quite as useful is it?

Microsoft Lync takes this a step further with Federation and will allow you to communicate with a SIP URI that is not part of your organization. Now instead of having to hunt down that phone number to call a business partner you can communicate using an easy to remember SIP URI that more than likely matches their E-mail address. Add them to your contact list in Microsoft Lync and communicating with that business partner is even easier.

Want a more in depth talk about where I think all this is going. Read my blog post on why the days of the telephone number are dwindling.

Working from Anywhere
When I started with Nortel, one of the first things I asked my hiring manager if he had any preference on where I lived. He stated as long as I have a phone line and an airport nearby, he did not care where I lived.

At the time, I was limited by technology as to where I worked... primary by where there was a phone line.

Fast forward 14 years, and now with new wireless technologies, I can get an Internet connection just about anywhere (3G/4G) and Microsoft Lync allows for communication with or without VPN. Cisco Expressway seems to give similar features for Cisco Jabber which I believe validates Microsoft's strategy for Federated and Remote Access to a Unified Communications environment. Microsoft first put this technology in to the product during LCS/OCS time frame.

My point isn't about comparing Unified Communication systems, the point is that technology shouldn't get in the way of the user trying to work. If you need to take the car to your local Big O Tire center to have some work done, why can't you work using the provided Wi-Fi? Added benefit... now you don't have to make up the time later and take away time from your family. Win-Win in my book.

On the flip side, since we can work from anywhere, work is now invading our personal lives more and more. Work/Life balance was/is a challenge without technology like Unified Communications.

Teleworkers have to develop Rules of Engagement when they are working from home. Just because Dad or Mom is home doesn't necessarily mean they are accessible when they are working. Here are some things I've found helpful.
  • Set aside space for an office. Working on any piece of furniture sends the wrong message to others that you are not working and can be approached anytime.
  • Train others that if the door to the office is shut, knock before entering
  • Train others to not speak right away. Have visual queues if someone is on the phone or not
  • Lync devices that show presence visually are very helpful (CX 300, Busy Light etc)
  • If your spouse, partner or roommate needs to communicate set them up on O365 Lync or Public IM so they can see your presence and send Instant Messages that are less disruptive
  • When you are not at work, try to give your family/others your full attention. They will respect your work time, if you respect personal time with them.
Working through these issues is crucial. It takes hard work and time to adjust for everyone.

Although Jason Fried is a bit extreme in some of his thinking... he does make you think about Why work doesn't happen at work anymore...

Escalation to other Modalities
Microsoft Lync has several modalities that can be used to communicate. But communication really does not become "Unified" until you start using multiple modalities at the same time. Examples:
  • Audio and Video
  • Audio and Collaboration like Desktop Sharing
  • Starting with an Instant Message and Escalating to Audio
When you use more than one modality to communicate, you add addition context.

Have you ever tried to explain a Visio diagram using just your voice?

Have you ever felt like your Instant Message just was not getting message across properly and your intent being misunderstood?

Being able to use multiple modalities at once is why you can't compare Microsoft Lync to just a PBX. Yes, Microsoft Lync can replace a PBX (I do this all the time), but the two can't be compared across the board.

Effective use of Presence
Most people encounter presence when they use a typical public Instant Message like Skype or Facebook. Knowing when a person is online is crucial to communicating in real time. However, many Unified Communication systems including Microsoft Lync expand on presence to communicate more than just whether someone is online or not.

For example, Microsoft Lync indicates when a person is on a call, in a conference, in a meeting, busy, away, inactive, or do not disturb.

Microsoft Lync does a great job setting presence automatically for the user.

If you a user has a Meeting scheduled in Outlook, Lync changes your presence to "In a Meeting".

If a user just has some time blocked out in Outlook to work on a task, Lync changes the users presence to "Busy".

Not at your computer for a few minutes... "Inactive".

Not at your computer for a longer period of time... "Away".

Think about that for a second... What different choices in communication would you make knowing when a person is not available for a phone call?

If you can see that a person is "In a Call", why give them a call when more than likely you will end up in their voicemail. If you still need to communicate you can now choose Instant Message and eliminate the productivity sucking phenomenon of voicemail tag.

If that person is Away, now you might choose to contact them later or send an E-mail. If you still want to send that Instant Message they are notified of the Missed Message in their Outlook mailbox.

Another scenario to think about is when a users presence indicates they are "In a Meeting". Bring up their contact card and now you will know when they are free next. With this crucial bit of information, you can now decide to accomplish another task or take that long lunch you deserve.

Here is a scenario in the etiquette department. When you want to communicate with a user that indicates they are "In a conference call", there is a possibility their screen is being viewed by others. You should always start off with an IM that is fairly generic like "Can you IM?" Nothing is more embarrassing then a private or confidential IM being displayed to others that shouldn't see it.

Knowing how to communicate with others based on their presence is a key skill to have. But you should also consider what your presence looks to others.

Are you a presence liar and show "Away" all the time because you don't want to be bothered with interruptions?

Maybe you should use Do Not Disturb for those times you need to not have interruptions and then let Lync manage your presence all the other times.

If your presence is always accurate, others will learn to believe it and respect it.

Business to Business Communications
Microsoft Lync is a great product hands down, but what makes Unified Communications more valuable is when you have more choices of people to talk to. Federation is Microsoft's not so secret weapon in the Unified Communication industry.

With Federation, you can communicate with partner organizations whether they have Lync or not. The Lync Federation Project has documented 18,000+ organizations that Federate using Microsoft Unified Communications. However, Lync will also Federate to MSN/Skype, AOL and any other XMPP compatible systems.

With MSN/Skype you are not just limited to Presence and Instant Messages, Audio and soon Video will be supported.

My customers sometimes don't get Federation until I have them do a conference call with someone at Microsoft and myself and then share my desktop. With a simple click and drag we are all talking and can collaborate.

If you have Open Federation like Time2Market, you can discover people that can Federate with you through their presence that shows up in an E-mail from them. Yet again highlighting the complete vision Microsoft had with making Unified Communications more than just in one application.


Monday, November 4, 2013

Updated: Script(s) to Backup AudioCodes Gateways

Backup of an AudioCodes gateway with a script has been on my list to do for a long time. Not sure why I didn't have the brain storm earlier, but I used Wireshark to take apart the backup process and see what is being done.

When I saw the HTTP GET in Wireshark for the file, I initially thought I could download just the BOARD.ini file, but then I found that GWs with 6.4 firmware or later have the Serial Number as part of the BOARD file name (BOARD_SN1234567.ini).

So back to the drawing board... I then had to step back and look at the page that was downloaded to give the interface to perform backups and pull out the filename used in the URL to request the file.

Anyway... I'm quite proud of hacking this together. Enjoy.

If you are running on a Windows 7 or other workstation you'll need to set your PowerShell Execution Policy.



Version 6.4 and older

# Script to Backup AudioCodes Gateways
# Created By Jonathan McKinney (blog.lyncdialog.com)
# Disclaimer: You running this script means you won't blame Jonathan McKinney or his employer if this breaks your stuff. This script is provided AS IS without warranty of any kind.

$username = "Admin"
$password = "Admin"
$regex = "BOARD.*\.ini"
$address = "10.10.1.10"
$path = "c:\scripts\"


$webclient = new-object System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($username, $password)

Write-Host `r`n 'Detecting .ini name' `r`n
$configurl = "http://" + $address + "/ConfigurationFile"
$webpage = $webclient.DownloadString($configurl)
$pattern = $webpage -split "`n" | Select-String -pattern $regex -Allmatches | % { $_.Matches | % { $_.Value } }
Write-Host `r`n 'Detected Board Filename ' $pattern


Write-Host  `r`n 'Backing up ' $address `r`n
$backupurl = "http://" + $address + "/FS/" + $pattern
$backupfilename = $path + $pattern
$webclient.DownloadFile($backupurl,$backupfilename)
Write-Host  `r




Version 6.6 and newer

So I have to admit that this was a huge pain to figure out. So I am even more proud I got this working than the above script. Having that been said... I consider this beta until more people test this and have success. Please give me feedback if you run into problems.

Audiocodes implemented Forms Based Authentication starting on version 6.6. Since I didn't understand much about this, I had to do a lot of research and found there are 1000 different variations on this, which made it hard to find examples of what I needed to do. So once again I went back to my trusty friend Wireshark and picked apart what was being sent in the HTTP POST versus what Audiocodes was doing in javascript.

There are some pre-requisites in order for this script to run successfully.To start with you will need to set the HTTP Authentication Mode on the Audiocodes to "Web Based Authentication", as illustrated below (note you will need to switch to "Advanced" on the left). This is necessary because there is a bunch of HASH algorithms that Audiocodes has running in javascript otherwise, that I can't deal with from a command line script (Note: this is a change from the original script I wrote that didn't handle the more complicated Hash algorithm used with Web Based Authentication).



Next you will need to install a package called cURL that is a command line tool for interacting with web pages. It is required to work with the Forms Based Auth that audiocodes uses. I used a new tool to install it called Chocolatey, which is the equivalent of RPM packages for Windows. Here is the page for cURL (http://chocolatey.org/packages/curl) and here is the main page for Chocolatey (http://chocolatey.org/)

This script now supports MediaPacks and Mediants on version 6.6 and newer.

# Script to Backup AudioCodes Gateways
# Created By Jonathan McKinney (blog.lyncdialog.com)
# Disclaimer: You running this script means you won't blame Jonathan McKinney or his employer if this breaks your stuff. This script is provided AS IS without warranty of any kind.


$username = "Admin"
$password = "Admin"
$login1sregex = "\<s\>(\d*)\<\/s\>"
$login1rregex = "\<r\>(.*)\<\/r\>"
$filenameregex = "BOARD.*\.ini"
$address = "10.10.1.10"
$path = "c:\scripts\"

$a1 = $null
$loginusername = $null
$loginurl = $null
$configurl = $null
$backupurl = $null
$logoffurl = $null
$logoffwebpage = $null
$login1webpage = $null
$login1spattern = $null
$login1rpattern = $null
$hashByteArray1 = $null
$hashByteArray2 = $null
$passwordhash = $null
$resultwebpage = $null
$configwebpage = $null
$filenamepattern = $null
$backupfilename = $null



# Authentication Section

Write-Host `r`n 'Authenticating' `r`n
$login1username = "c1=" + $username
$loginurl = "http://" + $address + "/UE/Login"
$login1webpage = curl $loginurl --data-urlencode "t=1" `
                                --data-urlencode "c0=0" `
                                --data-urlencode $login1username `
                                --header "X-Requested-With: XMLHttpRequest" `
                                -c cookiejar.txt `
                                --header "Cookie: aclogname=; C2=ct" `
                                --user-agent "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"

$login1spattern = $login1webpage -split "`n" | Select-String -pattern $login1sregex -Allmatches | % { $_.Matches | % { $_.groups[1].Value } }

$login1spattern = "s=" + $login1spattern

$login1rpattern = $login1webpage -split "`n" | Select-String -pattern $login1rregex -Allmatches | % { $_.Matches | % { $_.groups[1].Value } }

$cryptoServiceProvider = [System.Security.Cryptography.SHA256CryptoServiceProvider]
$hashAlgorithm = New-Object $cryptoServiceProvider
$hashByteArray1 = $hashAlgorithm.ComputeHash($([Char[]]$password))

foreach ($byte in $hashByteArray1)
{     $a1 += "{0:x2}" -f $byte
}$a2 = $username + ":" + $login1rpattern + ":" + $a1
$hashByteArray2 = $hashAlgorithm.ComputeHash($([Char[]]$a2))

foreach ($byte in $hashByteArray2)
{     $passwordhash += "{0:x2}" -f $byte
}$passwordhash = "c1=" + $passwordhash
$resultwebpage = curl $loginurl --data-urlencode "t=1" `
                                --data-urlencode $login1spattern `
                                --data-urlencode "c0=1" `
                                --data-urlencode $passwordhash `
                                --header "X-Requested-With: XMLHttpRequest" `
                                -c cookiejar.txt `
                                --header "Cookie: aclogname=; C2=ct" `
                                --user-agent "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"


# Detect filename for backup section

Write-Host `r`n 'Detecting .ini name' `r`n
$configurl = "http://" + $address + "/ConfigurationFile"
$configwebpage = curl $configurl -b cookiejar.txt

$filenamepattern = $configwebpage -split "`n" | Select-String -pattern $filenameregex -Allmatches | % { $_.Matches | % { $_.Value } }

Write-Host `r`n 'Detected Board Filename ' $filenamepattern


# Backup section

Write-Host `r`n 'Backing up ' $address `r`n
$backupurl = "http://" + $address + "/FS/" + $filenamepattern
$backupfilename = $path + $filenamepattern
curl -o $backupfilename $backupurl -b cookiejar.txt
Write-Host `r


# Logoff section

$logoffurl = "http://" + $address + "/PressLogOff"
$logoffwebpage = curl $logoffurl -b cookiejar.txt





Authentication type Auto Detect

And now... the pièce de résistance... I combined both scripts... decided to make it more Function based and now it Auto Detects the authentication type. It has the same prerequisites as the Scripts above. So please read all of the article before you try to use this script. Also if you are wondering why I didn't use cURL for all of the work in the new script... it kept truncating the authentication header when doing the basic (Digest) authentication and failing. Couldn't find a parameter to increase the header size allowed.

Enjoy... as usual... feedback is always welcome.

# Script to Backup AudioCodes Gateways# Created By Jonathan McKinney (blog.lyncdialog.com)# Disclaimer: You running this script means you won't blame Jonathan McKinney or his employer if this breaks your stuff. This script is provided AS IS without warranty of any kind.

# User Modifiable Variables

$username = "Admin"
$password = "Admin"
$address = "m2600.t2mdev.com"
$backuppath = "c:\jonmck\script\"


# End User Modifiable Variables
$filename = $null
$statuscodeeval = $null


#Function to detect if Forms Auth is present

function DetectAuthType ($ad)
{
     $loginurl = $null
     $loginurl = "http://" + $ad + "/"
     $statuscode = curl -o null.txt $loginurl -w '%{http_code}'

     If ($statuscode -eq "401")
     {
          $statuscodeeval = "basic"
     }

     ElseIf ($statuscode -eq "203")

     {
          $statuscodeeval = "forms"
     }     
     Else
     {
          $statuscodeeval = "neither"
     }     
     Remove-Item null.txt
     Return $statuscodeeval
}


# Function to Authenticate with Forms Auth

function AuthenticateForms ($un, $pw, $ad)
{
     $login1sregex = "\<s\>(\d*)\<\/s\>"
     $login1rregex = "\<r\>(.*)\<\/r\>"
     $a1 = $null
     $loginusername = $null
     $loginurl = $null
     $login1webpage = $null
     $login1spattern = $null
     $login1rpattern = $null
     $hashByteArray1 = $null
     $hashByteArray2 = $null
     $passwordhash = $null
     $resultwebpage = $null
     $formsbasedauth = $null
     
     Write-Host `r`n 'Forms Authentication' `r`n
     $login1username = "c1=" + $un
     $loginurl = "http://" + $ad + "/UE/Login"
     $login1webpage = curl $loginurl --data-urlencode "t=1" `
                                     --data-urlencode "c0=0" `
                                     --data-urlencode $login1username `
                                     --header "X-Requested-With: XMLHttpRequest" `
                                     -c cookiejar.txt `
                                     --header "Cookie: aclogname=; C2=ct" `
                                     --user-agent "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"

     $login1spattern = $login1webpage -split "`n" | Select-String -pattern $login1sregex -Allmatches | % { $_.Matches | % { $_.groups[1].Value } }

     $login1spattern = "s=" + $login1spattern
     $login1rpattern = $login1webpage -split "`n" | Select-String -pattern $login1rregex -Allmatches | % { $_.Matches | % { $_.groups[1].Value } }

     $cryptoServiceProvider = [System.Security.Cryptography.SHA256CryptoServiceProvider]
     $hashAlgorithm = New-Object $cryptoServiceProvider
     $hashByteArray1 = $hashAlgorithm.ComputeHash($([Char[]]$password))
     foreach ($byte in $hashByteArray1)
     {
          $a1 += "{0:x2}" -f $byte
     }
     
     $a2 = $username + ":" + $login1rpattern + ":" + $a1
     $hashByteArray2 = $hashAlgorithm.ComputeHash($([Char[]]$a2))

     foreach ($byte in $hashByteArray2)
     {
          $passwordhash += "{0:x2}" -f $byte
     }
     
     $passwordhash = "c1=" + $passwordhash
     $resultwebpage = curl $loginurl --data-urlencode "t=1" `
                                     --data-urlencode $login1spattern `
                                     --data-urlencode "c0=1" `
                                     --data-urlencode $passwordhash `
                                     --header "X-Requested-With: XMLHttpRequest" `
                                     -c cookiejar.txt `
                                     --header "Cookie: aclogname=; C2=ct" `
                                     --user-agent "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
}


# Function to Backup Gateway WITHOUT Forms Auth

function BackupBasic ($un, $pw, $ad, $path)
{
     $regex = "BOARD.*\.ini"
     $webclient = $null
     $configurl = $null
     $backupurl = $null
     $webpage = $null
     $pattern = $null
     $backupfilename = $null

     $webclient = new-object System.Net.WebClient
     $webclient.Credentials = New-Object System.Net.NetworkCredential($un, $pw)

     Write-Host `r`n 'Detecting .ini name' `r`n

     $configurl = "http://" + $ad + "/ConfigurationFile"
     $webpage = $webclient.DownloadString($configurl)
     $pattern = $webpage -split "`n" | Select-String -pattern $regex -Allmatches | % { $_.Matches | % { $_.Value } }
     Write-Host `r`n 'Detected Board Filename ' $pattern

     Write-Host `r`n 'Backing up ' $ad `r`n
     $backupurl = "http://" + $ad + "/FS/" + $pattern
     $backupfilename = $path + $pattern
     $webclient.DownloadFile($backupurl,$backupfilename)
     Write-Host `r
}


# Function to Detect the Backup Filename with Forms Auth for the Audiocodes Configuration File

function DetectFilenameForms ($ad)
{
     $fnregex = "BOARD.*\.ini"
     $configurl = $null
     $fnpat = $null
     $configwebpage = $null

     Write-Host `r`n 'Detecting .ini name' `r`n
     $configurl = "http://" + $ad + "/ConfigurationFile"
     $configwebpage = curl $configurl -b cookiejar.txt
     $fnpat = $configwebpage -split "`n" | Select-String -pattern $fnregex -Allmatches | % { $_.Matches | % { $_.Value } }

     Write-Host `r`n 'Detected Board Filename ' $fnpat
     return $fnpat
}


# Function to Backup Gateway with Forms Auth

function BackupGatewayForms ($ad, $path, $fn)
{
     $backupurl = $null
     $backupfilename = $null
     
     Write-Host `r`n 'Backing up ' $ad `r`n
     $backupurl = "http://" + $ad + "/FS/" + $fn
     $backupfilename = $path + $fn
     curl -o $backupfilename $backupurl -b cookiejar.txt
     Write-Host `r
}

# Function to Logoff Audiocodes with Forms Auth after finishing work

function LogoffForms ($ad)
{
     $logoffurl = $null
     $logoffwebpage = $null
     
     $logoffurl = "http://" + $ad + "/PressLogOff"
     $logoffwebpage = curl $logoffurl -b cookiejar.txt
     Remove-Item cookiejar.txt
}


# Main Script


$formsbasedauth = DetectAuthType $address

if ($formsbasedauth -eq "forms")
{
     AuthenticateForms $username $password $address
     $filename = DetectFilenameForms $address
     BackupGatewayForms $address $backuppath $filename
     LogoffForms $address
}
ElseIf ($formsbasedauth -eq "basic")
{
     BackupBasic $username $password $address $backuppath
}
Else
{
     Write-Host "Something went really wrong... couldn't detect Authentication type... Might I suggest Wireshark"
}