H323Transport GetLocalAddress bug using PTLIB>=2.11
We discovered this bug trying to register an endpoint (ip 62.22.27.131) to a gatekeeper (ip 62.22.20.229), using H323Plus v1.26.5 w ptlib 2.12.8.
As you can see in the trace log:
------------------------
0:00.010 Yate H323G...f3d7464700 transports.cxx(2363) RAS Gatekeeper discovery on interface: 62.22.27.131:59483 0:00.021 Yate H323G...f3d7464700 h323pdu.cxx(79) Trans Sending PDU [ip$62.22.27.131:59483/ip$62.22.20.229:1719] : gatekeeperRequest { requestSeqNum = 36153 protocolIdentifier = 0.0.8.2250.0.7 rasAddress = ipAddress { ip = 4 octets { 3e 16 1b 83 >... } port = 59483 }
^^^--- We see our RAS Address is set correctly (3e 16 1b 83 = 62.22.27.131) and port 59483 ... rest of the PDU trace has been trimmed ... }
0:00.076 Yate H323G...f3d7464700 h323pdu.cxx(79) H225RAS Receiving PDU [ip$62.22.20.229:54287/ip$62.22.20.229:1719] : gatekeeperConfirm { requestSeqNum = 36153 protocolIdentifier = 0.0.8.2250.0.7 gatekeeperIdentifier = 9 characters { 0047 004b 0040 0070 0070 0063 0069 0067 GK@ppcig 006b k } rasAddress = ipAddress { ip = 4 octets { 3e 16 14 e5 >... } port = 1719 } } Raw PDU: size=25 pos=25.0 { 000 04 80 8d 38 06 00 08 91 4a 00 07 10 00 47 00 4b 8 J G K 00 40 00 70 00 70 00 63 00 69 00 67 00 6b 00 3e @ p p c i g k > 16 14 e5 06 b7 } 0:00.076 Yate H323G...f3d7464700 gkclient.cxx(288) RAS Gatekeeper discovery found ip$62.22.20.229:1719 0:00.076 Yate H323G...f3d7464700 transports.cxx(2461) RAS Gatekeeper discovered at: 62.22.20.229:1719 (if=62.22.27.131:59483)
^^^^---- this transport still has the correct interface / local ip
0:00.076 Yate H323G...f3d7464700 osutil.cxx(189) PTLib File handle high water mark set: 26 Thread unblock pipe 0:00.077 Yate H323G...f3d7464700 tlibthrd.cxx(305) PTLib Created thread 0x7ff3b4008420 Transactor:%x 0:00.077 PTLib Hous...f3d7568700 osutils.cxx(2158) PTLib Cleaning 1 AutoDelete threads 0:00.077 Transactor:d31ab700 tlibthrd.cxx(354) PTLib Started thread 0x7ff3b4008420 (5287) "Transactor:d31ab700" 0:00.077 Transactor:d31ab700 h323trans.cxx(266) Trans Starting listener thread on Transport[remote=ip$62.22.20.229:1719 if=ip$62.22.20.229:54287]
^^^--- See that this new transport has a wrong "if=" (with remote GK address not our local address)
0:00.077 Yate H323G...f3d7464700 transports.cxx(749) TCP Appending H.225 transport ip$62.22.27.131:2720 using associated transport Transport[remote=ip$62.22.20.229:1719 if=ip$62.22.20.229:54287] 0:00.077 Transactor:d31ab700 h323trans.cxx(274) Trans Reading PDU 0:00.077 Transactor:d31ab700 tlibthrd.cxx(1012) PTLib PThread::PXBlockOnIO(22,0) 0:00.077 Yate H323G...f3d7464700 h323trans.cxx(435) Trans Making request: registrationRequest 0:00.077 Yate H323G...f3d7464700 h323pdu.cxx(79) Trans Sending PDU [ip$62.22.20.229:54287/ip$62.22.20.229:1719] : registrationRequest { requestSeqNum = 36154 protocolIdentifier = 0.0.8.2250.0.7 discoveryComplete = true callSignalAddress = 1 entries { [0]=ipAddress { ip = 4 octets { 3e 16 1b 83 >... } port = 2720 }
^^^---- callSignalAddress is our endpoint IP address (62.22.27.131). Ok
} rasAddress = 1 entries { [0]=ipAddress { ip = 4 octets { 3e 16 14 e5 >... } port = 59483 } } ^^^--- rasAddress has been set incorrectly to the remote gatekeeper address (62.22.20.229) although the port is OK (it's the same used in the previous GRQ pdu) }
-------------------
By looking at the source code:
In transports.cxx, function H323TransportUDP::ReadPDU:
PBoolean H323TransportUDP::ReadPDU(PBYTEArray & pdu)
#if PTLIB_VER >= 2110 if (canGetInterface) { WORD notused; // TODO: verify that this actually does the same as the pre 2.11.x version socket->GetLastReceiveAddress(lastReceivedInterface, notused); } #else if (canGetInterface) lastReceivedInterface = socket->GetLastReceiveToAddress(); #endif
Since the PTLIB's version we are using is 2.12.8, the compiled code is as follows:
WORD notused; // TODO: verify that this actually does the same as the pre 2.11.x version socket->GetLastReceiveAddress(lastReceivedInterface, notused);
Be noticed the comment and that the name of the called function is not the same as the pre 2.11.x code: GetLastReceiveAddress() vs GetLastReceiveToAddress()
GetLastReceiveToAddress() returned local ip address but this function has been removed from PTLib and the existing function (the one is used) GetLastReceiveAddress returns the address of the *sender* in the last connection.
Due to use GetLastReceiveAddress, now lastReceivedInterface has the remote ip (62.22.20.229). And lastReceivedInterface is used in the function H323TransportUDP::GetLocalAddress():
H323TransportAddress H323TransportUDP::GetLocalAddress() const { if (canGetInterface && !lastReceivedInterface.IsLoopback()) return H323TransportAddress(lastReceivedInterface, interfacePort);
.....
returning lastReceivedInterface (62.22.20.229) as our local address incorrectly.
The GetLocalAddress function is used in many places so this can cause many problems as the one we have spotted here.
Hi Jose,
thanks for finding that bug. Do you have a patch I can apply to the CVS ?
The PTLib >= 2.11.x code didn't gte the same amount of testing as the older code. Thats why I still use PTLib 2.10.x for GnuGk.
Regards, Jan
-- Jan Willamowius, Founder of the GNU Gatekeeper Project EMail : jan@willamowius.de Website: http://www.gnugk.org Support: http://www.willamowius.com/gnugk-support.html
Relaxed Communications GmbH Frahmredder 91 22393 Hamburg Geschäftsführer: Jan Willamowius HRB 125261 (Amtsgericht Hamburg) USt-IdNr: DE286003584
Jose Uceda wrote:
We discovered this bug trying to register an endpoint (ip 62.22.27.131) to a gatekeeper (ip 62.22.20.229), using H323Plus v1.26.5 w ptlib 2.12.8.
As you can see in the trace log:
0:00.010 Yate H323G...f3d7464700 transports.cxx(2363) RAS Gatekeeper discovery on interface: 62.22.27.131:59483 0:00.021 Yate H323G...f3d7464700 h323pdu.cxx(79) Trans Sending PDU [ip$62.22.27.131:59483/ip$62.22.20.229:1719] : gatekeeperRequest { requestSeqNum = 36153 protocolIdentifier = 0.0.8.2250.0.7 rasAddress = ipAddress { ip = 4 octets { 3e 16 1b 83 >... } port = 59483 }
^^^--- We see our RAS Address is set correctly (3e 16 1b 83 = 62.22.27.131) and port 59483 ... rest of the PDU trace has been trimmed ...
}
0:00.076 Yate H323G...f3d7464700 h323pdu.cxx(79) H225RAS Receiving PDU [ip$62.22.20.229:54287/ip$62.22.20.229:1719] : gatekeeperConfirm { requestSeqNum = 36153 protocolIdentifier = 0.0.8.2250.0.7 gatekeeperIdentifier = 9 characters { 0047 004b 0040 0070 0070 0063 0069 0067 GK@ppcig 006b k } rasAddress = ipAddress { ip = 4 octets { 3e 16 14 e5 >... } port = 1719 } } Raw PDU: size=25 pos=25.0 { 000 04 80 8d 38 06 00 08 91 4a 00 07 10 00 47 00 4b 8 J G K 00 40 00 70 00 70 00 63 00 69 00 67 00 6b 00 3e @ p p c i g k > 16 14 e5 06 b7 } 0:00.076 Yate H323G...f3d7464700 gkclient.cxx(288) RAS Gatekeeper discovery found ip$62.22.20.229:1719 0:00.076 Yate H323G...f3d7464700 transports.cxx(2461) RAS Gatekeeper discovered at: 62.22.20.229:1719 (if=62.22.27.131:59483)
^^^^---- this transport still has the correct interface / local ip
0:00.076 Yate H323G...f3d7464700 osutil.cxx(189) PTLib File handle high water mark set: 26 Thread unblock pipe 0:00.077 Yate H323G...f3d7464700 tlibthrd.cxx(305) PTLib Created thread 0x7ff3b4008420 Transactor:%x 0:00.077 PTLib Hous...f3d7568700 osutils.cxx(2158) PTLib Cleaning 1 AutoDelete threads 0:00.077 Transactor:d31ab700 tlibthrd.cxx(354) PTLib Started thread 0x7ff3b4008420 (5287) "Transactor:d31ab700" 0:00.077 Transactor:d31ab700 h323trans.cxx(266) Trans Starting listener thread on Transport[remote=ip$62.22.20.229:1719 if=ip$62.22.20.229:54287]
^^^--- See that this new transport has a wrong "if=" (with remote GK address not our local address)
0:00.077 Yate H323G...f3d7464700 transports.cxx(749) TCP Appending H.225 transport ip$62.22.27.131:2720 using associated transport Transport[remote=ip$62.22.20.229:1719 if=ip$62.22.20.229:54287] 0:00.077 Transactor:d31ab700 h323trans.cxx(274) Trans Reading PDU 0:00.077 Transactor:d31ab700 tlibthrd.cxx(1012) PTLib PThread::PXBlockOnIO(22,0) 0:00.077 Yate H323G...f3d7464700 h323trans.cxx(435) Trans Making request: registrationRequest 0:00.077 Yate H323G...f3d7464700 h323pdu.cxx(79) Trans Sending PDU [ip$62.22.20.229:54287/ip$62.22.20.229:1719] : registrationRequest { requestSeqNum = 36154 protocolIdentifier = 0.0.8.2250.0.7 discoveryComplete = true callSignalAddress = 1 entries { [0]=ipAddress { ip = 4 octets { 3e 16 1b 83 >... } port = 2720 }
^^^---- callSignalAddress is our endpoint IP address (62.22.27.131). Ok
} rasAddress = 1 entries { [0]=ipAddress { ip = 4 octets { 3e 16 14 e5 >... } port = 59483 } } ^^^--- rasAddress has been set incorrectly to the remote gatekeeper address (62.22.20.229) although the port is OK (it's the same used in the previous GRQ pdu) }
By looking at the source code:
In transports.cxx, function H323TransportUDP::ReadPDU:
PBoolean H323TransportUDP::ReadPDU(PBYTEArray & pdu) #if PTLIB_VER >= 2110 if (canGetInterface) { WORD notused; // TODO: verify that this actually does the same as the pre
2.11.x version socket->GetLastReceiveAddress(lastReceivedInterface, notused); } #else if (canGetInterface) lastReceivedInterface = socket->GetLastReceiveToAddress(); #endif
Since the PTLIB's version we are using is 2.12.8, the compiled code is as follows: WORD notused; // TODO: verify that this actually does the same as the pre 2.11.x version socket->GetLastReceiveAddress(lastReceivedInterface, notused); Be noticed the comment and that the name of the called function is not the same as the pre 2.11.x code: GetLastReceiveAddress() vs GetLastReceiveToAddress() GetLastReceiveToAddress() returned local ip address but this function has been removed from PTLib and the
existing function (the one is used) GetLastReceiveAddress returns the address of the *sender* in the last connection.
Due to use GetLastReceiveAddress, now lastReceivedInterface has the remote ip (62.22.20.229).
And lastReceivedInterface is used in the function H323TransportUDP::GetLocalAddress():
H323TransportAddress H323TransportUDP::GetLocalAddress() const { if (canGetInterface && !lastReceivedInterface.IsLoopback()) return H323TransportAddress(lastReceivedInterface, interfacePort);
.....
returning lastReceivedInterface (62.22.20.229) as our local address incorrectly.
The GetLocalAddress function is used in many places so this can cause many problems as the one we have spotted here.
Hi Jan:
On Thu, Jul 23, 2015 at 3:24 PM, Jan Willamowius jan@willamowius.de wrote:
Hi Jose, thanks for finding that bug. Do you have a patch I can apply to the CVS ?
Jose Uceda is my next-table colleague. We've been working on this together.
He put on a patch which solved the problem for us:
--- h323plus.orig/src/transports.cxx 2015-07-21 10:10:18.422143019 +0200 +++ h323plus/src/transports.cxx 2015-07-21 10:11:38.655442814 +0200 @@ -2066,5 +2066,5 @@
#if PTLIB_VER >= 2110 - canGetInterface = binding.IsAny(); + canGetInterface = FALSE; // juceda - disable bogus canGetInterface code #else canGetInterface = (binding.IsAny()) && udp->SetCaptureReceiveToAddress();
But we fear this may not be correct. To explain it I need to elaborate a little bit. Some of the things I'm writting have been deducted doing VC bisections and may not be acurate, so if someone is wronly named it's my fault. I'm going to explain the process.
When upgrading ptlib to 2.12 we lost gatekeeper operation, and traced it to the bug reported by Jose. Succintly, the RRQ packet got the IP part of the rasAddress transport address from the SOURCE of the GCF packet instead of the destination, so our gatekeeper sent a security denial RRJ due to the ACLs.
Then we traced the problem to the offending code, one of the variations of:
#if PTLIB_VER >= 2110 if (canGetInterface) { WORD notused; // TODO: verify that this actually does the same as the pre 2.11.x version socket->GetLastReceiveAddress(lastReceivedInterface, notused); } #else if (canGetInterface) lastReceivedInterface = socket->GetLastReceiveToAddress(); #endif
Pre 2.11 PTLIB had a method to capture and get the destination (local) address of a received packet, aptly named getLastReceived*To*Address, to distinguish it from the ( also present ) method GetLastReceiveAddress ( no To, it could have been named from ) which gets the source ( remote ) address of the received packet.
At some point in the 2.11 development socket code was changed. We think it was by Craig Southern, in case he reads this and wants to chip in. In this change the *TO* variation of the functions was removed. Near this time we think it was Craig too who changed transports.cxx to use the other function. We think that change is incorrect as instead of doing lastReceivedInterface=local destination address of received packet it sets it to remote source address. In facts two lines after the #if the same function is called again and it's result is assigned to remoteAddress.
After poking a bit we found that setting canGetInterface to false solves our problems, works FOR US. But I fear it works because none of our sockets are bound to INADDR_ANY, or something like this.
With my limited knowledge of h323+/ptlib it seems h323+ uses received address of the ras packet to refine its workings. And that it does it conditioned on the canGetInterface flag which, pre 2.11, was intialized to udp->SetCaptureReceiveToAddress(), as the binding.isAny() part is more a 'should get local address from the packet as I'm bound to INADDR_ANY'.
If this is acurate, as ptlib 2.12 has not a method to get the local destination address, I think the code for ptlib > 1.10 must be supressed, as using the REMOTE address instead of the local one is incorrect, and we think it's never going to do good. It may work with GK which do not use the rasAdress field on the RRQ for security / whatever and instead use the RRQ source address, but in this case anything will work, and will harm the ones like ours, and IIRC yours too, which do use it. If ptlib 2.11+ has a method to get it it must be used, but we were unable to find it, it seems its gone for good.
OTOH, given udp->SetCaptureReceiveToAddress() can fail ( I suppose because the socket library has no method to give it ), we feel our patch is not that bad, but also feel it works because it makes H323TransportUDP::ReadPDU(PBYTEArray & pdu) leave lastReceivedInterface empty. And we are nto knowledgeable enough to assert it, hence we will need some help.
The PTLib >= 2.11.x code didn't gte the same amount of testing as the older code. Thats why I still use PTLib 2.10.x for GnuGk.
We are doing the same presently, but as the h323+ page recomends 2.12.8 with 1.26.5 we tested it, as we do periodically, to peek the assorted bugfixes and new functionality which normally come with new releases, although 1.26 is giving us a hard time.
Regards. Francisco Olarte.
participants (3)
-
Francisco Olarte
-
Jan Willamowius
-
Jose Uceda