Showing posts with label Wireshark. Show all posts
Showing posts with label Wireshark. Show all posts

Thursday, August 21, 2014

So... you want to be a Lync Architect

For at least a couple years now my employer has been on a constant search for talent to deploy Microsoft Lync and the components that are part of that ecosystem. But it is getting harder to find guys that will fit in with the company culture and have a good set of fundamental skills (or phenomenal skills if we get lucky).

So I thought I'd write a post, from my perspective, about what some of the skills are that it takes to work as a consultant in this Microsoft Unified Communications world. Engineers and Architects that can do this type of work WELL are a rare find. They posses knowledge from multiple disciplines (data, voice, server apps, security etc) and combine them all to help a customer deploy a solution that fits their needs. My hope is that this will finally convince some people that are on the fence to jump in (and increase the pool of talent).

... and no you don't have to be an Architect to jump in, you can start out being an Engineer or working the support desk. You can learn as you go.


The Hard Skills

Here is the bottom line... the more of these the better.

The more of these you are excellent at... the better consultant or support engineer you'll be for your customer.

Nobody... Nobody will be an expert at all of these. But sometimes the secret is knowing others that are experts in that area... or knowing where/how to find the answers.

If you are weak in most these areas... no problem... go buy a computer, create a lab of your own and pick something and start to learn. With Microsoft based software there is usually no lack of freely available knowledge you can learn from and there are certainly plenty of books out there on all of these topics. Don't expect you will learn all of this in two weeks. I've been gathering knowledge for as far back as 20+ years and that knowledge still applies to what I do today. But everyone has to start somewhere.

Here is the list that I've come up with...
  • Active Directory
  • SQL Server
  • Windows XP/Vista/7/8/8.1 etc
  • Server 2008 R1/R2 and 2012 R1/R2
  • Office Communications Server 2007 R1/R2
  • Lync Server 2010/2013
  • Exchange 2007/2010/2013
  • System Center 2007/2012/2012 R2 via @fabriziovlp
  • Hyper Visors (Microsoft, VMWare etc) via @fabriziovlp
  • Virtual Desktop Infrastructure (Microsoft, VMWare, Citrix etc)
  • PowerShell
  • .Net Regular Expressions (RegEx)
  • Private Key Infrastructure/Certificates
  • Layer 2 Networking (Switched)
  • Layer 3 Networking (Routed)
  • IPv4
  • IPv6
  • TCP/IP
  • Quality of Service
  • Firewalls
  • Network Sniffer (Wireshark, Message Analyzer)
  • SIP
  • Audio Codecs (G.711 etc)
  • HTTP/HTTPS
  • ISDN PRI and the associated protocols/capabilities
  • T-1 (Telephony based digital circuit)
  • DS-1/DS-3 (Data based digital circuit)
  • Frame Relay
  • Avaya Blue (Nortel)
  • Avaya Red (Traditional Avaya)
  • Cisco Unified Call Manager
  • Mitel
  • Inter-tel (owned by Mitel now)
  • Shoretel
  • PBX Dial Plans
  • PBX Features
  • Analog device types
  • Fax and Fax Server
  • T.38 Codec (for Fax over IP)
  • Modem (Yes credit card and postage machines still use this)
  • Gateway/SBC (Sonus, Audiocodes, etc)


The Soft Skills
  • Good listening skills
  • Good presentation skills
  • Good communications skills (verbal and written)
  • Patience
  • Attitude toward constant learning
  • Self starter
  • Working alone
  • Working in teams
  • Working with other teams
  • Juggling lots of tasks/jobs at once
  • Prioritizing tasks
  • Bing/Google searching for information
  • Networking (the people kind)

Getting There...

This one is all on you. My unique path took me from being a network manager/admin at a University, to working 11 years for Nortel and then combining all that experience into what I do now. Some of this is hard to learn in a lab unless you are loaded with money. 

You need to surround yourself with people that know about the skills you need to work on. This is where the networking (the people kind) really comes in handy.

How do you do this?

  • Go to local users groups
  • Go to local conferences. 
  • Go to some industry conferences. 
  • Get on twitter and follow people that tweet about the things you want to learn about. 
  • Get on LinkedIn and make some connections and join some discussion groups. 
  • Read the Technet forums
  • Read some books
I'll keep updating this as I think of things... but bottom line is that this stuff isn't easy, but it is something that is able to be learned given enough time and effort.

Monday, June 9, 2014

AT&T Hosted Firewall preventing Desktop/Application Sharing through Lync Edge

Issue

Ran into this problem a while ago and just now getting around to writing about it... but it is one of those head scratch kind of problems, until you compare a working system with the non-working system. In this case, I spotted the problem of Desktop/Application Sharing across the Lync Edge server in Wireshark when the client went to STUN the server on port 443.

I didn't realize this, but there actually is a momentary TLS negotiation on 443 STUN and the failure from the AT&T Hosted Firewall looked like this.



From the Lync Edge server perspective everything was successful. But the AT&T Hosted Firewall in the middle of the TLS negotiation was sending back this "Level: Fatal, Description: Access Denied" error instead of what the Lync Edge Server responded with. This was both an issue for Lync Server 2010 and 2013.

Resolution

The jist of the resolution was to request AT&T to do a Policy Bypass for the IP Addresses associated with the Lync Edge server. The problem was with STUN, but I would probably ask they bypass any other IPs if you have multiple IP addresses on your Lync Edge servers.

Just in case that doesn't get you far enough... I have below verbatim what was send back... so that you can coax the Level 1 support technician to find someone that really knows what they are doing (my cust went through several support people before he found someone that could fix this).
“What I did to correct the issue is to remove the Protocol Option filter from rule 4 and rule 17 in the policy that was being used for the Lync traffic.  Protocol options tell the firewall to check further into known traffic types such as http, https, smtp, ftp, etc. for expected settings.  On the HTTPS side one of those checks is ‘Allow invalid SSL certificates’ which is not enabled by default.  Since the filter is used by most of your rules in your policy I didn’t want to enable this and have all of those rules using it so instead I removed the filter from these two rules.  If you would like it re-applied but with the setting enabled a separate filter can be configured with that setting enabled and just apply that filter to the two rules.”

Tuesday, May 20, 2014

Chocolatey - RPM style package management for Windows

While I was researching how to deal with Forms Based Authentication from a script perspective, for my Audiocodes backup script(s), I stumbled upon Chocolatey. Chocolatey NuGet (love the name) is a Machine Package Manager similar to what RPMs are for Linux. This allows crazy simple install and uninstall of software from PowerShell... silently.

There are currently 1872 unique packages available and they install with a simple command like:

     cinst sysinternals

Simple, eh?

If you want to install Chocolatey just go to their home page and run the install command from within a cmd window. Then search for packages that are interesting to you...

Here are some that are my favorites so far:

Sysinternals
http://chocolatey.org/packages/sysinternals

PuTTY
http://chocolatey.org/packages/putty

Fiddler
http://chocolatey.org/packages/fiddler

cURL
http://chocolatey.org/packages/curl

Wireshark
http://chocolatey.org/packages/wireshark

Anyway... you get the idea... now go have some fun!

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









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"
}