On 2014-03-03 09:09, Dmitry Sytchev wrote:
The problem is the method people often use to limit concurrent calls. Something like that:
<action application="limit" data="hash OutboundLimit ${pbx_subscriber_customer_id} ${pbx_customer_call_limit} !CALL_REJECTED"/> <action application="bridge" data="{ignore_early_media=false,hangup_after_bridge=false}sofia/gateway/gw/$1"/>
Now limit is set on inbound channel. When attacker bridges outbound channels, their A-legs (inbound channels) get destroyed and FS decreases limit due to channel destruction. So attacker have 2 outbound bridged channels, and limit is still 0. Then the process repeats, allowing attacker effectively bypass your call limits.
One of possible solutions is to move limits on B-legs after answer, while keeping limits on A-legs too in order prevent exceeding limit by unanswered calls:
We set limit on A-LEG, then on answer we decrease limit on A-LEG and "move" it to B-leg by calling limit on outbound channel.
<action application="export" data="nolocal:execute_on_answer_1=set api_result=${uuid_limit_release(${uuid} hash OutboundLimit ${pbx_subscriber_customer_id})}"/> <action application="export" data="nolocal:execute_on_answer_2=limit hash OutboundLimit ${pbx_subscriber_customer_id} ${pbx_customer_call_limit} !CALL_REJECTED"/> <action application="limit" data="hash OutboundLimit ${pbx_subscriber_customer_id} ${pbx_customer_call_limit} !CALL_REJECTED"/> <action application="bridge" data="{ignore_early_media=false,hangup_after_bridge=false}sofia/gateway/gw/$1"/>
This is approximately correct. Note that you could use api_on_answer for the API call there, and you could use arrays ("push") instead of the _N suffixes. There is a race condition here; the resource could go over-limit between being released on the a-leg and being reacquired on the b-leg. That wouldn't be a big deal for fraud control, but it would mean the a-leg user might not be appropriately notified. The correct solution here may be that we need to add a uuid_limit_exchange function to atomically move a limit between legs.