From c48928321c6bc5030d15a42d461794df5985db0f Mon Sep 17 00:00:00 2001
From: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Date: Fri, 17 Jun 2016 11:39:12 +0200
Subject: [PATCH] Bug 15006: [COUNTERPATCH] Add timeout and strikes to
 raw_transport
Content-Type: text/plain; charset=utf-8

The code in raw_transport includes setting a $SIG{ALRM}, but did not
use it. For consistency, we add an alarm statement here.

Similarly, we add the "three strikes" to raw_transport just as
telnet_transport does. Note that raw_transport will no longer respond
to other requests than login.

Test plan:
[1] Start sip session with telnet on raw port 6001.
    Wait until it times out (probably the default 60 seconds).
[2] Change SIPconfig.xml: set timeout=5 for service port 6001.
    Restart SIP and start another telnet 6001 session.
    Did it timeout within 5 seconds?
[3] Start another 6001 session. Give three wrong requests or false
    login attempts. Does the connection close?

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
---
 C4/SIP/SIPServer.pm |   26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/C4/SIP/SIPServer.pm b/C4/SIP/SIPServer.pm
index 6cde3ae..50473ed 100755
--- a/C4/SIP/SIPServer.pm
+++ b/C4/SIP/SIPServer.pm
@@ -124,20 +124,34 @@ sub process_request {
 
 sub raw_transport {
     my $self = shift;
-    my ($input);
     my $service = $self->{service};
+    my $strikes = 3;
 
-    while (!$self->{account}) {
-        local $SIG{ALRM} = sub { die "raw_transport Timed Out!\n"; };
-        syslog("LOG_DEBUG", "raw_transport: timeout is %d", $service->{timeout});
-        $input = read_SIP_packet(*STDIN);
+    local $SIG{ALRM} = sub { die "raw_transport Timed Out!\n"; };
+    my $timeout = $service->{timeout} || 30;
+    syslog("LOG_DEBUG", "raw_transport: timeout is %d", $timeout);
+
+    while( $strikes && ( !$self->{account} || !$self->{account}->{id} )) {
+    # an empty account hash is not good enough..
+        alarm $timeout;
+        my $input = read_SIP_packet(*STDIN);
         if (!$input) {
             # EOF on the socket
             syslog("LOG_INFO", "raw_transport: shutting down: EOF during login");
             return;
         }
         $input =~ s/[\r\n]+$//sm; # Strip off trailing line terminator(s)
-        last if C4::SIP::Sip::MsgType::handle($input, $self, LOGIN);
+        my $login_req = LOGIN;
+        if( $input =~ /^$login_req/ ) {
+            # In this loop we are only responding to login attempts
+            C4::SIP::Sip::MsgType::handle($input, $self, LOGIN);
+        }
+        $strikes--;
+    }
+    alarm 0;
+    if( !$self->{account}->{id} ) {
+        syslog("LOG_ERR", "raw_transport: Login Failed");
+        die "Login Failure";
     }
 
     syslog("LOG_DEBUG", "raw_transport: uname/inst: '%s/%s'",
-- 
1.7.10.4