0

I have an sh script that is listening to log output. When it finds an IP address under certain conditions, it need to send a curl request out to that IP address (Receiver is a Polycom VoIP phone if it matters).

On the receiver, I am getting:

PushParserC::parseDoc: Expecting <PolycomIPPhone>: $'<PolycomIPPhone><Data

where as a correct line produces this:

wappPushHandlerC::Handle: <PolycomIPPhone><Data priority="Critical">Key:Setup

and on a -v dump of curl I get:

curl: (6) Could not resolve host: priority="Critical">Key.... < should be an IP address

In both cases, it looks like communication is being cut the at white space in my script. Most solutions get rid of the whitespace, but that breaks the XHTML that is expected.

My script is below

#!/bin/sh

tail -0f /var/log/somelogfile.log | while read line
do
  if echo $line | grep "\[WARNING\]" | grep -q "SIP auth failure" ; then

    # Log detected sip authentication error to file
    STR="$(echo $line | awk '{print "Date:",$1,"Time:",$2,"Login:",$14,"IP:",$17}')" >> logger.txt

    # Get the found private IP address out of the errored line
    IP="$(echo $STR | rev | cut -d" " -f1 | rev)"

    # Provide output to the user of the IP to brute
    echo "Target IP: " $IP

    # Content Type header
    CT="Content-Type: application/x-com-polycom-spipx"

    # The XHTML to send to the phone in question for forced factory reset
    XHTML="curl -v --digest -u Push:Push -d $'<PolycomIPPhone><Data priority=\"Critical\">Key:Setup\nKey:Dialpad2\nKey:Dialpad9\nKey:Dialpad9\nKey:Dialpad9\nKey:Softkey4\nKey:Dialpad1\nKey:Dialpad5\nKey:Dialpad5</Data></PolycomIPPhone>' --header \"$CT\" $IP/push"

    # print out URL for test
    echo $XHTML
    RESPONSE=`$XHTML`
    echo
    echo $RESPONSE
  fi
done


# This is an example of the fuctional code that works straight in the terminal.
# curl --digest -u Push:Push -d $'<PolycomIPPhone><Data priority="Critical">Key:Setup\nKey:Dialpad2\nKey:Dialpad9\nKey:Dialpad9\nKey:Dialpad9\nKey:Softkey4\nKey:Dialpad1\nKey:Dialpad5\nKey:Dialpad5</Data></PolycomIPPhone>' --header "Content-Type: application/x-com-polycom-spipx" xx.xx.xx.xx/push && echo

Other solutions remove whitespace which isn't possible in this context or encode. Neither of which work in this application though!

Thanks!

Ari
  • 130
  • You try to build the command line in a variable $XHTML and then execute its contents, but that tokenizes at all whitespace -- unless you use doublequotes " in which case it doesn't tokenize at all which also fails. The easy solution is do the command directly in the script not in a variable; if you want to see it as well use the builtin set -x. An alternative in bash ksh zsh is to use an array variable with each intended token as an element and execute (and display) "${array[@]}" -- but in sh as you shebang'ed (contrary to your tag) this is a good bit harder. – dave_thompson_085 Feb 22 '17 at 16:12
  • PSs: also in any modern shell you could use [[ $line == *\[WARNING\]* && $line == *SIP\ auth\ failure* ]] instead of two greps, and ${line##* } instread of rev-cut-rev. And your STR=$(..) >>logger.txt doesn't actually write anything to the file. – dave_thompson_085 Feb 22 '17 at 16:35
  • @dave_thompson_085, I really appreciate your second comment. It was really nice of you to provide positive criticism to better my coding into something better. Could you look at my comment below and see if I can get the \n character to send using @Archemar 's answer? – Ari Feb 23 '17 at 07:14
  • Use Awk. Period. None of this logic belongs in a shell script. The whole thing should consist of tail -f file.log | awk -f scriptfile.awk. See Why is using a shell loop to process text considered bad practice? and learn the system() function in Awk. – Wildcard Feb 24 '17 at 02:45

2 Answers2

0

for -d option, I would try

echo '$<PolycomIPPhone><Data priority=\"Critical\">....' | curl -d@- (other options)

according to man curl

If you start the data with the letter @, the rest should be a file name to read the data from, or - if you want curl to read the data from stdin.

Archemar
  • 31,554
  • I'm running the following based on your advice echo $'<PolycomIPPhone><Data priority="Critical">Key:Setup\nKe...</Data></PolycomIPPhone>' | curl -v --digest -u push:push -d@- --header "Content-Type: application/x-com-polycom-spipx" 192.168.100.71/push and the phone is definitively getting contacted. It looks like the \n is getting stripped on before getting the receiver end. Also note that the $ is outside the quote and that I "unescaped" the double quote. Amazingly, I can send the first key Key:Setup (before the first \n) and it works so far. Any hint to get the \n in there? – Ari Feb 23 '17 at 07:11
  • try printf or echo -e – Archemar Feb 23 '17 at 07:16
  • Neither work unfortunately. When I escape the \n it get's sent, but does not get interpreted by the phone as a newline – Ari Feb 23 '17 at 07:33
0

Using both @Archemar and @dave_thompson_085 assistance, I was able to make a working solution.

To get around whitespace and newline issues when sending or receiving, I made a file with said contents and "actual" newline characters. Piping the new file into curl still gave me the same issues until I discovered sending the contents as a "form" which kept the formatting intact.

It's definitely cool to see such an issue resolved in an automated way.

Thanks again guys

#!/bin/bash
# Sends a data file to the phone using curl
tail -0f /var/log/freeswitch/freeswitch.log | while read line
do
    if [[ $line == *\[WARNING\]* && $line == *SIP\ auth\ failure* ]] ; then

        STR="$(echo $line | awk '{print "Date:",$1,"Time:",$2,"IP:",$17,"Login:",$14}')" # Pull important lines from log
        IP="${line##* }" # Store private IP address of failed auth
        CT="Content-Type: application/x-com-polycom-spipx" # Content Type header
        OCCUR=`grep "$IP" logger.txt | wc -l` # Count of how many failed attempts to auth

        # Provide output to the terminal
        echo -n "TargetIP:" $IP

        # If there are less than 6 attemps at authenticating, send commands to phone
        if [ $OCCUR -le 5 ] ; then

            echo " Formatting with" $OCCUR "previous attepts."

            # Log the parsed string from the log with attempt status
            echo "Status: FORMAT" $STR >> logger.txt

            # Send user a HTML warning screen
            curl -s --digest -u push:push -d "<PolycomIPPhone><Data priority='"critical"'><h1> PHONE WILL UPDATE </h1>Please do not interact with the phone. It will now format and restart. Contact IT support for any concerns</Data></PolycomIPPhone>" --header $CT $IP/push  > /dev/null

            # Allow for user read time
            sleep 8

           # Send instruction set phone in question for forced factory reset
            curl -s --digest -u push:push --form "fileupload=@send.txt" --header "$CT" $IP/push  > /dev/null

       # If there are 6 failed attempts, log to file for further action
       elif [ $OCCUR -eq 6 ] ; then
            echo " Too many attempts. Logging..."
            echo "Status: FAILED" $STR >> logger.txt

       # Beyond 6 attemps, no action will be taken
       else
            echo " IGNORED"
       fi
    fi
done
Ari
  • 130