Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Eclipse Titan » Using TLS/DTLS with Titan test ports part 5 (HTTP/TLS/TCP with the IPL4 port and the HTTP2.0 protocol module)
Using TLS/DTLS with Titan test ports part 5 [message #1755816] Wed, 08 March 2017 12:02 Go to next message
Elemer Lelik is currently offline Elemer LelikFriend
Messages: 1120
Registered: January 2015
Senior Member
Chapter 5. HTTPS with the HTTP protocol module (https://github.com/eclipse/titan.ProtocolModules.HTTP2.0) and the IPL4 test port (https://github.com/eclipse/titan.TestPorts.IPL4asp) in DTLS/UDP mode (requires https://github.com/eclipse/titan.TestPorts.Common_Components.Socket-API)

Besides illustrating the usage of the security layer, this is a good example of how Titan test ports and protocol
modules can be used together to build a protocol stack.
In the previous example (HTTPS with the HTTP test port) all three layers (HTTP/TLS/TCP) were handled by the test port.
In this example the HTTP layer will be covered by the HTTP protocol module, while TLS and TCP by the IPL4 test port:


    +------------------------------------------+
    |                                          |
    |             HTTP(HTTP PM)                |
    |                                          |
    |                                          |
    +------------------------------------------+
    |                                          |
    |             TLS(IPL4 TP)                 |
    |                                          |
    |                                          |
    +------------------------------------------+
    |                                          |
    |             TCP(IPL4 TP)                 |
    |                                          |
    |                                          |
    +------------------------------------------+


There is an important difference to the previous example though: the TCP layer deals with streams of bits and it's totally agnostic to the structure of the messages carried in the stream.
All such knowledge belongs to the upper layer.
To enable the IPL4 port to dissect the TCP stream into messages , structural information has to be communicated to it.
This wil be done in the form of a dissection function to be registered with the port.
(In case of the HTTP port this algorithm is part of the test port code, but for the IPL4 port it has to come with the protocol
using the port; hence all protocol modules aiming to use the IPL4 test port will have to include such a dissection function.)

Instead of the HTTP PM, the protocol desciption part of the HTTP test port could be used as well (the HTTP port also includes a message dissection fucntion).
In fact there is little difference between the protocol definition of the test port and of the protocol module; the latter is somewhat user-friendlier.
And one more thing: the HTTP protocol module is misleadingly named HTTP2.0: it has nothing to do with HTTP/2 , it's just the second version of the protocol description
and it covers HTTP 1.0 and HTTP 1.1.

This time we will be using the HTTP Request & Response Service at https://httpbin.org/:

anything posted to https://httpbin.org/post is returned in a JSON answer:
 curl -X POST -d something -v  https://httpbin.org/post
*   Trying 23.22.14.18...
* Connected to httpbin.org (23.22.14.18) port 443 (#0)
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: none
* TLSv1.2, TLS handshake, Client hello (1):
* TLSv1.2, TLS handshake, Server hello (2):
* NPN, negotiated HTTP1.1
* TLSv1.2, TLS handshake, CERT (11):
* TLSv1.2, TLS handshake, Server key exchange (12):
* TLSv1.2, TLS handshake, Server finished (14):
* TLSv1.2, TLS handshake, Client key exchange (16):
* TLSv1.2, TLS change cipher, Client hello (1):
* TLSv1.2, TLS handshake, Unknown (67):
* TLSv1.2, TLS handshake, Finished (20):
* TLSv1.2, TLS change cipher, Client hello (1):
* TLSv1.2, TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
* 	 subject: OU=Domain Control Validated; OU=EssentialSSL Wildcard; CN=*.httpbin.org
* 	 start date: 2017-01-09 00:00:00 GMT
* 	 expire date: 2018-01-29 23:59:59 GMT
* 	 subjectAltName: httpbin.org matched
* 	 issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Domain Validation Secure Server CA
* 	 SSL certificate verify ok.
> POST /post HTTP/1.1
> Host: httpbin.org
> User-Agent: curl/7.42.0
> Accept: */*
> Content-Length: 9
> Content-Type: application/x-www-form-urlencoded
> 
* upload completely sent off: 9 out of 9 bytes
< HTTP/1.1 200 OK
< Server: nginx
< Date: Mon, 06 Mar 2017 19:27:58 GMT
< Content-Type: application/json
< Content-Length: 359
< Connection: keep-alive
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true
< 
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "something": ""
  }, 
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "9", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "curl/7.42.0"
  }, 
  "json": null, 
  "origin": "94.21.64.179", 
  "url": "https://httpbin.org/post"
}
* Connection #0 to host httpbin.org left intact





Openssl and Titan versions used are the same as in the previous examples.

The relevant sections of the config file:


[MODULE_PARAMETERS]

HTTPTest.tsp_hostname:="httpbin.org"
HTTPTest.tsp_portnumber:=443
HTTPTest.tsp_url:="/post"

[TESTPORT_PARAMETERS]


*.p.debug := "Yes"
*.p.ssl_reconnect_attempts := "100"
*.p.ssl_verify_certificate := "Yes"
*.p.ssl_trustedCAlist_file:= "/etc/ssl/certs/ca-certificates.crt"//Ubuntu 16.04


The TTCN-3 code used:

module HTTPTest {


modulepar {

charstring tsp_hostname:="httpbin.org"  
integer    tsp_portnumber:=443
charstring tsp_url:="/post" 
 
}

import from IPL4asp_Types all;
import from IPL4asp_PortType all;
import from HTTP_Types all;
import from HTTP_MessageLen all;


//------------------------------------------------------------------------------
function f_ContentLength (in charstring par_body)  return integer
//------------------------------------------------------------------------------

{
 
  return (lengthof (par_body))

}



//*************************************************************************
function f_HTTPMessage_len(  in octetstring stream,   inout ro_integer args) return integer
//*************************************************************************

{    
  return ef_HTTPMessage_len(stream) ;                
}


  type component GeneralComp
    {
        port IPL4asp_PT p;
        timer t;    
      var IPL4asp_Types.Result  c_res:= { errorCode := omit, connId  := omit, os_error_code:=omit, os_error_text:= omit };   
        
    }
    
    type component SystemComp
    {
        port IPL4asp_PT p;
    }



template  ASP_Send t_data1(in integer p_id ) :={
   connId:=p_id,
  proto:=omit,
  msg:=ef_HTTP_Encode(valueof(t_message("Bow to your Titan overlords!")))
}

	template HTTP_Message t_message (in charstring payload) := {
	  	msg := {{request_line :={POST,tsp_url,1,1}},{
			host := tsp_hostname,
			cache_control := {{"no-cache"}},
		        content_length := f_ContentLength(payload)
		},char2oct(payload)}
	}with { optional "implicit omit" } 
	


  testcase TC_TCPTest() runs on GeneralComp system SystemComp {
	
			
    var IPL4asp_Types.Result  vl_result; 
    var integer v_cid
    map(self:p, system:p); 

  vl_result := c_res;

  vl_result :=f_IPL4_connect(
    p,
    tsp_hostname,
    tsp_portnumber,
    "",//default 0.0.0.0 will be used
     0,//random port will be used
    -1,  
   {ssl := {} },
 //{tcp := {} },
     {}
  )


  log("connect result",vl_result)

  if (not(ispresent(vl_result.connId)))
  {
    log("Could not connect");
   stop;
  } 

   v_cid:=vl_result.connId 

//*************************************************************************
 var f_IPL4_getMsgLen getMsg_Func := refers(f_HTTPMessage_len);
 f_IPL4_setGetMsgLen(p,v_cid, getMsg_Func, {});
//*************************************************************************

 p.send(t_data1(v_cid));
   t.start(5.0) 
        alt 
        { 
              [] p.receive {repeat};
              [] t.timeout{log("Bye")}

        } 

  vl_result := c_res;

  vl_result :=    f_IPL4_close(p, v_cid)
  log("close result",vl_result) 
              
     setverdict(pass);
    }
	
    control{
        execute(TC_TCPTest());
    }



}


Note1: Please mind the message dissection function:

//this just a wrapper around ef_HTTPMessage_len , supplied with the HTTP PM:
//*************************************************************************
function f_HTTPMessage_len(  in octetstring stream,   inout ro_integer args) return integer
//*************************************************************************

{    
  return ef_HTTPMessage_len(stream) ;                
}


//*************************************************************************
 var f_IPL4_getMsgLen getMsg_Func := refers(f_HTTPMessage_len);
 f_IPL4_setGetMsgLen(p,v_cid, getMsg_Func, {});
//*************************************************************************



Note2: As the body in POST is of non-zero length, an appropriate Content-length header has to be added and calculated:

//------------------------------------------------------------------------------
function f_ContentLength (in charstring par_body)  return integer
//------------------------------------------------------------------------------
{
  return (lengthof (par_body))
}

template HTTP_Message t_message (in charstring payload) := {
	  	:
		        content_length := f_ContentLength(payload)
		:		
		},char2oct(payload)}
	}


The log reflects the expected behaviour, a JSON return is received:

00:11:08.004323 - TTCN-3 Main Test Component started on ntaf. Version: CRL 113 200/6 R1A.
00:11:08.004392 - TTCN Logger v2.2 options: TimeStampFormat:=Time; LogEntityName:=No; LogEventTypes:=No; SourceInfoFormat:=Single; *.FileMask:=LOG_ALL; *.ConsoleMask:=ERROR | USER; LogFileSize:=0; LogFileNumber:=1; DiskFullAction:=Error
00:11:08.004583 - Connected to MC.
00:11:08.005120 - Executing control part of module HTTPTest.
00:11:08.005155 HTTPTest.ttcn:126 Execution of control part in module HTTPTest started.
00:11:08.005276 HTTPTest.ttcn:72 Test case TC_TCPTest started.
00:11:08.005308 HTTPTest.ttcn:72 Initializing variables, timers and ports of component type HTTPTest.GeneralComp inside testcase TC_TCPTest.
00:11:08.005393 HTTPTest.ttcn:72 Port p was started.
00:11:08.005420 HTTPTest.ttcn:72 Component type HTTPTest.GeneralComp was initialized.
00:11:08.005437 HTTPTest.ttcn:77 Mapping port mtc:p to system:p.
00:11:08.005514 HTTPTest.ttcn:77 Port p was mapped to system:p.
00:11:08.005579 HTTPTest.ttcn:77 Map operation of mtc:p to system:p finished.
00:11:08.005613 HTTPTest.ttcn:81 entering f__IPL4__PROVIDER__connect: :0 -> httpbin.org:443 / SSL
00:11:08.449834 HTTPTest.ttcn:94 connect result{
    errorCode := omit,
    connId := 1,
    os_error_code := omit,
    os_error_text := omit
}
00:11:08.451245 HTTPTest.ttcn:109 Sent on p to system @IPL4asp_Types.ASP_Send : {
    connId := 1,
    proto := omit,
    msg := '504F5354202F706F737420485454502F312E310D0A43616368652D436F6E74726F6C3A206E6F2D63616368650D0A436F6E74656E742D4C656E6774683A2032380D0A486F73743A206874747062696E2E6F72670D0A0D0A426F7720746F20796F757220546974616E206F7665726C6F72647321'O ("POST /post HTTP/1.1\r
Cache-Control: no-cache\r
Content-Length: 28\r
Host: httpbin.org\r
\r
Bow to your Titan overlords!")
}
00:11:08.451756 HTTPTest.ttcn:110 Start timer t: 5 s
00:11:08.575807 HTTPTest.ttcn:111 Message enqueued on p from system @IPL4asp_Types.ASP_RecvFrom : {
    connId := 1,
    remName := "httpbin.org",
    remPort := 443,
    locName := "192.168.139.129",
    locPort := 39416,
    proto := {
        ssl := { }
    },
    userData := 0,
    msg := '485454502F312E3120323030204F4B0D0A5365727665723A206E67696E780D0A446174653A204D6F6E2C203036204D617220323031372030383A31313A303920474D540D0A436F6E74656E742D547970653A206170706C69636174696F6E2F6A736F6E0D0A436F6E74656E742D4C656E6774683A203238350D0A436F6E6E656374696F6E3A206B6565702D616C6976650D0A4163636573732D436F6E74726F6C2D416C6C6F772D4F726967696E3A202A0D0A4163636573732D436F6E74726F6C2D416C6C6F772D43726564656E7469616C733A20747275650D0A0D0A7B0A20202261726773223A207B7D2C200A20202264617461223A2022426F7720746F20796F757220546974616E206F7665726C6F72647321222C200A20202266696C6573223A207B7D2C200A202022666F726D223A207B7D2C200A20202268656164657273223A207B0A202020202243616368652D436F6E74726F6C223A20226E6F2D6361636865222C200A2020202022436F6E74656E742D4C656E677468223A20223238222C200A2020202022486F7374223A20226874747062696E2E6F7267220A20207D2C200A2020226A736F6E223A206E756C6C2C200A2020226F726967696E223A202239312E38322E3130302E3539222C200A20202275726C223A202268747470733A2F2F6874747062696E2E6F72672F706F7374220A7D0A'O ("HTTP/1.1 200 OK\r
Server: nginx\r
Date: Mon, 06 Mar 2017 08:11:09 GMT\r
Content-Type: application/json\r
Content-Length: 285\r
Connection: keep-alive\r
Access-Control-Allow-Origin: *\r
Access-Control-Allow-Credentials: true\r
\r
{
  \"args\": {}, 
  \"data\": \"Bow to your Titan overlords!\", 
  \"files\": {}, 
  \"form\": {}, 
  \"headers\": {
    \"Cache-Control\": \"no-cache\", 
    \"Content-Length\": \"28\", 
    \"Host\": \"httpbin.org\"
  }, 
  \"json\": null, 
  \"origin\": \"91.82.100.59\", 
  \"url\": \"https://httpbin.org/post\"
}
")
} id 1
00:11:08.576181 HTTPTest.ttcn:113 Receive operation on port p succeeded, message from system(): @IPL4asp_Types.ASP_RecvFrom: {
    connId := 1,
    remName := "httpbin.org",
    remPort := 443,
    locName := "192.168.139.129",
    locPort := 39416,
    proto := {
        ssl := { }
    },
    userData := 0,
    msg := '485454502F312E3120323030204F4B0D0A5365727665723A206E67696E780D0A446174653A204D6F6E2C203036204D617220323031372030383A31313A303920474D540D0A436F6E74656E742D547970653A206170706C69636174696F6E2F6A736F6E0D0A436F6E74656E742D4C656E6774683A203238350D0A436F6E6E656374696F6E3A206B6565702D616C6976650D0A4163636573732D436F6E74726F6C2D416C6C6F772D4F726967696E3A202A0D0A4163636573732D436F6E74726F6C2D416C6C6F772D43726564656E7469616C733A20747275650D0A0D0A7B0A20202261726773223A207B7D2C200A20202264617461223A2022426F7720746F20796F757220546974616E206F7665726C6F72647321222C200A20202266696C6573223A207B7D2C200A202022666F726D223A207B7D2C200A20202268656164657273223A207B0A202020202243616368652D436F6E74726F6C223A20226E6F2D6361636865222C200A2020202022436F6E74656E742D4C656E677468223A20223238222C200A2020202022486F7374223A20226874747062696E2E6F7267220A20207D2C200A2020226A736F6E223A206E756C6C2C200A2020226F726967696E223A202239312E38322E3130302E3539222C200A20202275726C223A202268747470733A2F2F6874747062696E2E6F72672F706F7374220A7D0A'O ("HTTP/1.1 200 OK\r
Server: nginx\r
Date: Mon, 06 Mar 2017 08:11:09 GMT\r
Content-Type: application/json\r
Content-Length: 285\r
Connection: keep-alive\r
Access-Control-Allow-Origin: *\r
Access-Control-Allow-Credentials: true\r
\r
{
  \"args\": {}, 
  \"data\": \"Bow to your Titan overlords!\", 
  \"files\": {}, 
  \"form\": {}, 
  \"headers\": {
    \"Cache-Control\": \"no-cache\", 
    \"Content-Length\": \"28\", 
    \"Host\": \"httpbin.org\"
  }, 
  \"json\": null, 
  \"origin\": \"91.82.100.59\", 
  \"url\": \"https://httpbin.org/post\"
}
")
} id 1
00:11:08.576461 HTTPTest.ttcn:113 Message with id 1 was extracted from the queue of p.
00:11:13.457355 HTTPTest.ttcn:114 Timeout t: 5 s
00:11:13.457456 HTTPTest.ttcn:114 Bye
00:11:13.457545 HTTPTest.ttcn:120 p: f__IPL4__close:  proto {
    unspecified := { }
} connId 1
00:11:13.458063 HTTPTest.ttcn:121 close result{
    errorCode := omit,
    connId := 1,
    os_error_code := omit,
    os_error_text := omit
}
00:11:13.458136 HTTPTest.ttcn:123 setverdict(pass): none -> pass
00:11:13.458168 HTTPTest.ttcn:123 Terminating component type HTTPTest.GeneralComp.
00:11:13.458184 HTTPTest.ttcn:123 Removing unterminated mapping between port p and system:p.
00:11:13.458203 HTTPTest.ttcn:123 Port p was unmapped from system:p.
00:11:13.458233 HTTPTest.ttcn:123 Port p was stopped.
00:11:13.458248 HTTPTest.ttcn:123 Component type HTTPTest.GeneralComp was shut down inside testcase TC_TCPTest.
00:11:13.458263 HTTPTest.ttcn:123 Waiting for PTCs to finish.
00:11:13.458684 HTTPTest.ttcn:123 Setting final verdict of the test case.
00:11:13.458723 HTTPTest.ttcn:123 Local verdict of MTC: pass
00:11:13.458746 HTTPTest.ttcn:123 No PTCs were created.
00:11:13.458766 HTTPTest.ttcn:123 Test case TC_TCPTest finished. Verdict: pass
00:11:13.458790 HTTPTest.ttcn:127 Execution of control part in module HTTPTest finished.
00:11:13.459438 - Verdict statistics: 0 none (0.00 %), 1 pass (100.00 %), 0 inconc (0.00 %), 0 fail (0.00 %), 0 error (0.00 %).
00:11:13.459489 - Test execution summary: 1 test case was executed. Overall verdict: pass
00:11:13.459507 - Exit was requested from MC. Terminating MTC.



The full debug log and the code archive is attached.

Best regards
Elemer

[Updated on: Wed, 08 March 2017 13:54]

Report message to a moderator

Re: Using TLS/DTLS with Titan test ports part 5 [message #1759371 is a reply to message #1755816] Mon, 10 April 2017 22:05 Go to previous message
Elemer Lelik is currently offline Elemer LelikFriend
Messages: 1120
Registered: January 2015
Senior Member
Update:

Dear all,

as I was playing with this code for another small project , I realized that it does not work anymore: the TLS connection attempt fails.
even when using opensssl,
openssl s_client -connect httpbin.org:443   -CAfile /etc/ssl/certs/ca-certificates.crt

(which used to work) will not connect , but

openssl s_client -connect httpbin.org:443  --servername httpbin.org -CAfile /etc/ssl/certs/ca-certificates.crt

will.

The reason most likely is that the owners of httpbin.org have migrated to an SNI (Server Name Indication ) setup, where on the same host
several servers with different certificates are run. You can read more about this here:

https://en.wikipedia.org/wiki/Server_Name_Indication

The IPL4 port from revision R25A has support for "servername";
it has to be sent as an option in the connect message.
So the code has to be modified as below:

  vl_result :=f_IPL4_connect(
    p,
    tsp_hostname, //httpbin.org
    tsp_portnumber, //443
    "",//default 0.0.0.0 will be used
     0,//random port will be used
    -1,  
   {ssl := {} },
   {{tls_hostname := "httpbin.org"}}
  )


where tls_hostname will act as the servername required for handshake.
If not present , the handshake will fail as the node cannot decode which certificate belonging to which server on the node ought to be used.



Best regards
Elemer


Previous Topic:IPL4 port TCP connection problem
Next Topic:Compilation of big files
Goto Forum:
  


Current Time: Wed Apr 24 17:33:54 GMT 2024

Powered by FUDForum. Page generated in 0.03852 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top