When Asterisk Gotos attack



  • So, we do the whole "phone support center" thing, being an ISP and all. And every so often, we have a POP that goes offline, generating a bunch of calls from people connected to that POP. So, the phone system has a menu that support can use to put up a temporary "we're really sorry, but customers in area X are being effected by a big outage, and of course we're working double hard on getting y'all fixed" message.

    Recently, we took over phone support for another ISP that's kind of a sister company to us. Of course, at the time, nobody really thought about making sure there was a way to play an outage message for the sister company. Which became a BIG FREAKING DEAL last night as I was relaxing at home, since major outage.

    "Oh well, no big deal, I'll just copy the existing context and then prepend the sister company's name to the context and the recording filename and the ASTDB variable that determines whether or not the outage message gets played to callers. Five minute fix, tops!" I thought to myself...

    [supportmessage]
    exten => s,1,Answer()
    same => n,Background(custom/listen-to-status-message&custom/change-status-message)
    same => n,ExecIf($[${DB(supportmessage/status)}=1]?Background(custom/deactivate-status-message):Background(custom/activate-status-message))
    same => n,WaitExten(10)
    same => n,Goto(supportmessage,s,1)
    
    exten => 1,1,Playback(custom/supportmessage)
    same => n,Wait(2)
    same => n,Goto(supportmessage,s,1)
    
    exten => 2,1,Record(/tmp/asterisk-recording:gsm)
    same => n,Wait(2)
    same => n,Playback(/tmp/asterisk-recording)
    same => n,Read(AcceptMessage,custom/to-save-status-message,1,,1,5)
    same => n,ExecIf($[${AcceptMessage}=1]?System(/bin/mv -f /tmp/asterisk-recording.gsm /var/lib/asterisk/sounds/en/custom/supportmessage.gsm))
    same => n,Wait(2)
    same => n,Goto(supportmessage,s,1)
    
    exten => 3,1,ExecIf($[${DB(supportmessage/status)}=1]?Set(DB(supportmessage/status)=0):Set(DB(supportmessage/status)=1))
    same => n,ExecIf($[${DB(supportmessage/status)}=0]?Playback(custom/status-message-is-no-longer-active):Playback(custom/status-message-is-now-active))
    same => n,Goto(supportmessage,s,1)
    

    Specifying a context name to goto an extension in the same context you're already in?!?! TDEMSYR!!!

    sigh Here's my dCAP badge, I'mma go now.



  • @izzion said:

    Specifying a context name to goto an extension in the same context you're already in?!?!

    Could an asterisk-literate poster clarify the WTF here?



  • Basically, the syntax for Goto is:

    Goto([context, [extension]], priority)

    So, if you're in logic like:

    [foo]
    exten => 1,1,DoSomething()
    exten => 1,2,Goto(1)
    

    Then Goto will auto-fill to Goto(foo,1,1) and you'll have an infinite loop going on. But you could specify Goto(bar,1,1) to jump off somewhere else, or Goto(2,1) to jump to extension 2, priority 1 in [foo].

    Apparently I was a little out of it when I originally wrote the [supportmessage] context, and used Goto(supportmessage,s,1) to loop back to the menu, rather than just using Goto(s,1). Which would have saved me a lot of hassle (and presses of the delete key) when I went to copy it to [newcompany-supportmessage] last night.


  • :belt_onion:

    @izzion said:

    Which would have saved me a lot of hassle (and presses of the delete key) when I went to copy it to [newcompany-supportmessage] last night.

    Ah, there it is. I was wondering what your exact problem is, since I didn't think that specifying the context would break it in any case.



  • For more Asterisk Goto fun... https://issues.asterisk.org/jira/browse/ASTERISK-20313.

    CLOSEDJUSTADOCUMENTATIONBUG


  • :belt_onion:

    Ugh, my brain keeps shutting down whenever I read that Asterisk script. Must be self-preservation kicking in.



  • So Asterisk uses this Goto command because it doesn't support subroutines or functions?


  • :belt_onion:

    @LoremIpsum said:

    So Asterisk uses this Goto command because it doesn't support subroutines or functions?

    Kind of...

    Since I don't want to repeat myself:

    http://what.thedailywtf.com/t/asterisk-pbx/1235

    First post has some GoTo / GoSub info.


  • :belt_onion:

    So I finally read the bug report and the code. Damn, I forgot how ugly .conf files are.

    I never used DUNDI so I'm guessing here - current context is not updated properly? Meh.

    Until you start tracking AMI events live and realize some of the channel shuffling that happens in the background, you haven't seen madness.

    I also ran into a situation where something akin to GoTo (as in, used to execute jumps) didn't update the priority properly, so if you jumped from context X to context Y at priority 3, it would keep executing in Y at priority 4. Can't remember what it was though, and I'm pretty sure it didn't allow you to set the priority prior to jumping, so I had a few NoOps in place to make it behave.



  • @Onyx said:

    Until you start tracking AMI events live and realize some of the channel shuffling that happens in the background, you haven't seen madness.

    I don't know what any of this means, but I'm sure you're right.


  • :belt_onion:

    @boomzilla said:

    I don't know what any of this means, but I'm sure you're right.

    Asterisk Manager Interface basically throws an event for every thing Asterisk does internally: creates channels, rings the extensions, bridges calls, all that jazz.

    Now you'd think that, when you have a complete control of every data stream in the system, you could just bridge anything anywhere, easy-peasy. Fuck no. The thing makes about 2 extra temporary channels which immediately get discarded (and do fucks knows what for a few milliseconds they are alive) just to transfer a call.

    Why in the holy fuck don't they just skip all that madness, I do not know, and do not intend to find out. It's probably full of casts and whatnots.

    Did I mention Asterisk is written in pure C?


Log in to reply
 

Looks like your connection to What the Daily WTF? was lost, please wait while we try to reconnect.