From 78962c1f0df218785ebb7c9155e208fff25a7737 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Fri, 7 Oct 2022 11:25:27 +0200 Subject: [PATCH 01/37] Bug fixed on params type --- ccsrc/Protocols/UDP/udp_layer.hh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ccsrc/Protocols/UDP/udp_layer.hh b/ccsrc/Protocols/UDP/udp_layer.hh index c24d833..90657b2 100644 --- a/ccsrc/Protocols/UDP/udp_layer.hh +++ b/ccsrc/Protocols/UDP/udp_layer.hh @@ -17,6 +17,11 @@ #include "layer.hh" +<<<<<<< HEAD +======= +#include "params.hh" + +>>>>>>> Bug fixed on params type using namespace std; // Required for isnan() #include "Abstract_Socket.hh" @@ -27,7 +32,11 @@ using namespace std; // Required for isnan() * \brief This class provides description of ITS UDP/IP protocol layer */ class udp_layer : public layer, public PORT { +<<<<<<< HEAD params _params; //! Layer parameters +======= + params _params; //! Layer parameters +>>>>>>> Bug fixed on params type struct sockaddr_in _saddr; //! Source socket address description struct sockaddr_in _daddr; //! Destination socket address description bool _reuse_incoming_source_adddress; -- GitLab From 50b768f28d9505433ee2a8301aa989f0ac3901e4 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Thu, 3 Nov 2022 08:34:42 +0100 Subject: [PATCH 02/37] Enhance TLS support --- ccsrc/Protocols/Tcp/tcp_layer.cc | 14 ++++++++++---- ccsrc/Protocols/UDP/udp_layer.hh | 9 --------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/ccsrc/Protocols/Tcp/tcp_layer.cc b/ccsrc/Protocols/Tcp/tcp_layer.cc index e134867..18dea58 100644 --- a/ccsrc/Protocols/Tcp/tcp_layer.cc +++ b/ccsrc/Protocols/Tcp/tcp_layer.cc @@ -85,7 +85,7 @@ void tcp_layer::init() { } parameter_set(use_connection_ASPs_name(), (!server_mode) ? "yes" : "no"); - loggers::get_instance().warning("tcp_layer::set_parameter: Limit to one simultanneous accepted connection (server_backlog == 1"); + loggers::get_instance().warning("tcp_layer::set_parameter: Limit to one simultanneous accepted connection (server_backlog == 1)"); parameter_set(server_backlog_name(), "1"); // Limit to one simultanneous accepted connection loggers::get_instance().log("tcp_layer::init: server_mode=%x", server_mode); set_server_mode(server_mode); @@ -108,20 +108,26 @@ void tcp_layer::init() { if (it != _params.cend()) { parameter_set(ssl_trustedCAlist_file_name(), it->second.c_str()); } else { - parameter_set(ssl_trustedCAlist_file_name(), "/home/yann/var/ssl/archive/yanngarcia.ddns.net/fullchain1.pem"); + // Use Let's Encrypt to generate your certificates + // https://manpages.ubuntu.com/manpages/impish/en/man1/certbot.1.html + loggers::get_instance().error("tcp_layer::set_parameter: Trusted CA list is required for TLS"); } // Set additional certificates it = _params.find(params::privkey); if (it != _params.cend()) { parameter_set(ssl_private_key_file_name(), it->second.c_str()); } else { - parameter_set(ssl_private_key_file_name(), "/home/yann/var/ssl/archive/yanngarcia.ddns.net/privkey1.pem"); + // Use Let's Encrypt to generate your certificates + // https://manpages.ubuntu.com/manpages/impish/en/man1/certbot.1.html + loggers::get_instance().error("tcp_layer::set_parameter: Certificate private key is required for TLS"); } it = _params.find(params::certificate); if (it != _params.cend()) { parameter_set(ssl_certificate_file_name(), it->second.c_str()); } else { - parameter_set(ssl_certificate_file_name(), "/home/yann/var/ssl/archive/yanngarcia.ddns.net/fullchain1.pem"); + // Use Let's Encrypt to generate your certificates + // https://manpages.ubuntu.com/manpages/impish/en/man1/certbot.1.html + loggers::get_instance().error("tcp_layer::set_parameter: Certificate is required for TLS"); } } set_ttcn_buffer_usercontrol(false); diff --git a/ccsrc/Protocols/UDP/udp_layer.hh b/ccsrc/Protocols/UDP/udp_layer.hh index 90657b2..c24d833 100644 --- a/ccsrc/Protocols/UDP/udp_layer.hh +++ b/ccsrc/Protocols/UDP/udp_layer.hh @@ -17,11 +17,6 @@ #include "layer.hh" -<<<<<<< HEAD -======= -#include "params.hh" - ->>>>>>> Bug fixed on params type using namespace std; // Required for isnan() #include "Abstract_Socket.hh" @@ -32,11 +27,7 @@ using namespace std; // Required for isnan() * \brief This class provides description of ITS UDP/IP protocol layer */ class udp_layer : public layer, public PORT { -<<<<<<< HEAD params _params; //! Layer parameters -======= - params _params; //! Layer parameters ->>>>>>> Bug fixed on params type struct sockaddr_in _saddr; //! Source socket address description struct sockaddr_in _daddr; //! Destination socket address description bool _reuse_incoming_source_adddress; -- GitLab From a24f37489fd2fb50bfcd3a35b3e8e094a9c2bf6a Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Thu, 3 Nov 2022 14:33:55 +0100 Subject: [PATCH 03/37] Bug fixed in ethernet_layer.cc after renaming ethernet_layer::receive_data parameters --- ccsrc/Protocols/ETH/ethernet_layer.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ccsrc/Protocols/ETH/ethernet_layer.cc b/ccsrc/Protocols/ETH/ethernet_layer.cc index 134d4d7..33a79e1 100644 --- a/ccsrc/Protocols/ETH/ethernet_layer.cc +++ b/ccsrc/Protocols/ETH/ethernet_layer.cc @@ -68,7 +68,7 @@ void ethernet_layer::receive_data(OCTETSTRING& p_data, params& p_params) { // Extract ethertype OCTETSTRING proto = OCTETSTRING(2, 2 + static_cast(p_data)); //loggers::get_instance().log_msg("ethernet_layer::receive_data: proto: ", proto); - OCTETSTRING data = OCTETSTRING(data.lengthof() - 14, 14 + static_cast(p_data)); + OCTETSTRING data = OCTETSTRING(p_data.lengthof() - 14, 14 + static_cast(p_data)); // Update params CHARSTRING s = oct2str(dst); p_params.insert(std::pair(params::mac_dst, std::string(static_cast(s)))); -- GitLab From ce12efc05a8efd8b480d54ba051159585aee7a90 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Tue, 8 Nov 2022 09:48:04 +0100 Subject: [PATCH 04/37] Enhance titan-test-system-framework with XSD --- ccsrc/Framework/include/codec_gen.hh | 2 +- ccsrc/Framework/include/layer.hh | 2 +- ccsrc/Framework/include/layer_factory.hh | 58 ---- ttcn/LibHttp/module.mk | 1 + ttcn/LibHttp/module_cise.mk | 19 ++ ttcn/LibJson/module.mk | 2 - ttcn/LibXsd/module.mk | 3 + ttcn/LibXsd/ttcn/UsefulTtcn3Types.ttcn | 95 +++++++ ttcn/LibXsd/ttcn/XSD.ttcn | 338 +++++++++++++++++++++++ 9 files changed, 458 insertions(+), 62 deletions(-) create mode 120000 ttcn/LibHttp/module.mk create mode 100644 ttcn/LibHttp/module_cise.mk create mode 100644 ttcn/LibXsd/module.mk create mode 100644 ttcn/LibXsd/ttcn/UsefulTtcn3Types.ttcn create mode 100644 ttcn/LibXsd/ttcn/XSD.ttcn diff --git a/ccsrc/Framework/include/codec_gen.hh b/ccsrc/Framework/include/codec_gen.hh index 82cfc8b..b36664c 100644 --- a/ccsrc/Framework/include/codec_gen.hh +++ b/ccsrc/Framework/include/codec_gen.hh @@ -50,7 +50,7 @@ public: //! \publicsection */ virtual int encode(const TPDUEnc &p_message, OCTETSTRING &p_data) = 0; /*! - * \fn int decode(const OCTETSTRING& p_, TPDUDec& p_message, params_its* p_params = NULL); + * \fn int decode(const OCTETSTRING& p_, TPDUDec& p_message, params* p_params = NULL); * \brief Encode typed message into an octet string format * \param[in] p_data The message in its octet string * \param[out] p_message The decoded typed message diff --git a/ccsrc/Framework/include/layer.hh b/ccsrc/Framework/include/layer.hh index 8268401..b42e68d 100644 --- a/ccsrc/Framework/include/layer.hh +++ b/ccsrc/Framework/include/layer.hh @@ -102,7 +102,7 @@ public: //! \publicsection /*! * \virtual - * \fn void receive_data(OCTETSTRING& data, params_its& params); + * \fn void receive_data(OCTETSTRING& data, params& params); * \brief Receive bytes formated data from the lower layers * \param[in] p_data The bytes formated data received * \param[in] p_params Some lower layers parameters values when data was received diff --git a/ccsrc/Framework/include/layer_factory.hh b/ccsrc/Framework/include/layer_factory.hh index 7b8ac35..68e99c5 100644 --- a/ccsrc/Framework/include/layer_factory.hh +++ b/ccsrc/Framework/include/layer_factory.hh @@ -36,52 +36,10 @@ public: //! \publicsection * \param[in] p_params Optional parameters * \return 0 on success, -1 otherwise * \remark The description below introduces layers stack in case of ITS project: - * CAM layer - * next_header : btpA|btpB (overwrite BTP.type) - * header_type : tsb|gbc - * header_sub_type : sh (single hop) - * DENM layer - * next_header : btpA|btpB (overwrite BTP.type) - * header_type : tsb|gbc - * BTP layer - * type : btpA|btpB - * destination port: dst_port - * source port : src_port - * device_mode : Set to 1 if the layer shall encapsulate upper layer PDU - * GN layer - * its_aid : ITS AID as defined by ETSI TS 102 965 V1.2.1. Default: 141 - * ll_address : GeoNetworking address of the Test System - * latitude : latitude of the Test System - * longitude : longitude of the Test System - * beaconing : Set to 1 if GnLayer shall start beaconing - * Beaconing timer expiry : expiry (ms) - * device_mode : Set to 1 if the layer shall encapsulate upper layer PDU - * secured_mode : Set to 1 if message exchanges shall be signed - * encrypted_mode : Set to 1 if message exchanges shall be encrypted - * NOTE: For signed & encrypted message exchanges, both secured_mode and encrypted_mode shall be set to 1 - * certificate : Certificate identifier the Test Adapter shall use - * secure_db_path : Path to the certificates and keys storage location - * hash : Hash algorithm to be used when secured mode is set - * Authorized values are SHA-256 or SHA-384 - * Default: SHA-256 - * signature : Signature algorithm to be used when secured mode is set - * Authorized values are NISTP-256, BP-256 and BP-384 - * Default: NISTP-256 - * cypher : Cyphering algorithm to be used when secured mode is set * Ethernet layer * mac_src :Source MAC address * mac_bc :Broadcast address * eth_type : Ethernet type - * Commsignia layer - * mac_src : Device MAC address, used to discard packets - * To indicate no filering, use the value 000000000000 - * mac_bc : Broadcast address - * eth_type : Ethernet type, used to discard packets - * target_host : Device address - * target_port : Device port - * source_port : Test System port - * interface_id: Interface id, used to discard packets - * tx_power : TX power (dB) * UDP layer (IP/UDP based on Pcap) * dst_ip : destination IPv4 address (aa.bb.cc.dd) * dst_port: destination port @@ -99,22 +57,6 @@ public: //! \publicsection * frame_offset: Frame offset, used to skip packets with frame number < frame_offset * time_offset : Time offset, used to skip packets with time offset < time_offset * save_mode : 1 to save sent packet, 0 otherwise - * Here are some examples: - * GeoNetworking multiple component case: - * NodeB.geoNetworkingPort.params := -"GN(ll_address=04e548000001,latitude=43551050,longitude=10298730,beaconing=0,expiry=1000,its_aid=141)/COMMSIGNIA(mac_src=04e548000001,mac_bc=FFFFFFFFFFFF,eth_type=8947,target_host=10.200.1.101,target_port=7942,source_port=7943,its_aid=141,interface_id=2,tx_power=-32)/UDP(dst_ip=192.168.56.1,dst_port=12346,src_ip=192.168.156.4,src_port=12345)/ETH(mac_src=04e548000001,mac_dst=0A0027000011,eth_type=0800)/PCAP(mac_src=04e548000001,file=/home/vagrant/TriesAndDelete/etsi_its/testdata/TC_AUTO_IOT_DENM_RWW_BV_01_short.pcap,filter=and -(udp port 30000 or udp port 7943))" NodeC.geoNetworkingPort.params := -"GN(ll_address=70b3d5791b48,latitude=43551050,longitude=10298730,beaconing=0,expiry=1000,its_aid=141)/COMMSIGNIA(mac_src=70b3d5791b48,mac_bc=FFFFFFFFFFFF,eth_type=8947,target_host=10.200.1.101,target_port=7942,source_port=7943,its_aid=141,interface_id=2,tx_power=-32)/UDP(dst_ip=192.168.56.1,dst_port=12346,src_ip=192.168.156.4,src_port=12345)/ETH(mac_src=70b3d5791b48,mac_dst=0A0027000011,eth_type=0800)/PCAP(mac_src=70b3d5791b48,file=/home/vagrant/TriesAndDelete/etsi_its/testdata/TC_AUTO_IOT_DENM_RWW_BV_01_short.pcap,filter=and -(udp port 30000 or udp port 7943))" - * NodeB.geoNetworkingPort.params := -"GN(ll_address=04e548000001,latitude=43551050,longitude=10298730,beaconing=0,expiry=1000,its_aid=141)/ETH(mac_src=04e548000001,mac_dst=0A0027000011,eth_type=0800)/PCAP(mac_src=04e548000001,file=/home/vagrant/TriesAndDelete/etsi_its/testdata/TC_AUTO_IOT_DENM_RWW_BV_01.pcap,filter=and -ether src 04e548000001)" #NodeC.geoNetworkingPort.params := -"GN(ll_address=70b3d5791b48,latitude=43551050,longitude=10298730,beaconing=0,expiry=1000,its_aid=141)/ETH(mac_src=70b3d5791b48,mac_dst=0A0027000011,eth_type=0800)/PCAP(mac_src=70b3d5791b48,file=/home/vagrant/TriesAndDelete/etsi_its/testdata/TC_AUTO_IOT_DENM_RWW_BV_01.pcap,filter=and -ether src 70b3d5791b48)" - * UpperTester port based on UDP - * system.utPort.params := -"UT_GN/UDP(dst_ip=192.168.1.1,dst_port=12346,src_ip=192.168.156.4,src_port=12345)/ETH(mac_src=026f8338c1e5,mac_dst=0A0027000011,eth_type=0800)/PCAP(mac_src=0800275c4959,nic=enp0s8,filter=and -udp port 12346)" * \pure */ virtual layer *create_layer(const std::string &p_type, const std::string &p_params) = 0; diff --git a/ttcn/LibHttp/module.mk b/ttcn/LibHttp/module.mk new file mode 120000 index 0000000..26de716 --- /dev/null +++ b/ttcn/LibHttp/module.mk @@ -0,0 +1 @@ +module_cise.mk \ No newline at end of file diff --git a/ttcn/LibHttp/module_cise.mk b/ttcn/LibHttp/module_cise.mk new file mode 100644 index 0000000..516c376 --- /dev/null +++ b/ttcn/LibHttp/module_cise.mk @@ -0,0 +1,19 @@ +sources := \ + ttcn/LibHttp_BinaryMessageBodyTypes.ttcn \ + ttcn/LibHttp_EncdecDeclarations.ttcn \ + ttcn/LibHttp_Functions.ttcn \ + ttcn/LibHttp_JsonMessageBodyTypes.ttcn \ + ttcn/LibHttp_JsonTemplates.ttcn \ + ttcn/LibHttp_JSONTypes.ttcn \ + ttcn/LibHttp_MessageBodyTypes.ttcn \ + ttcn/LibHttp_Pics.ttcn \ + ttcn/LibHttp_Pixits.ttcn \ + ttcn/LibHttp_Templates.ttcn \ + ttcn/LibHttp_TestSystem.ttcn \ + ttcn/LibHttp_TypesAndValues.ttcn \ + ttcn/LibHttp_XMLTypes.ttcn \ + + +# Please, move and comment the module you need to overwrite tofit your project +# ttcn/LibHttp_XmlMessageBodyTypes.ttcn \ +# ttcn/LibHttp_XmlTemplates.ttcn diff --git a/ttcn/LibJson/module.mk b/ttcn/LibJson/module.mk index a5d3e3b..2d08756 100644 --- a/ttcn/LibJson/module.mk +++ b/ttcn/LibJson/module.mk @@ -1,4 +1,2 @@ sources := \ ttcn/Json.ttcn - -# Please, move and comment the module you need to overwrite tofit your project diff --git a/ttcn/LibXsd/module.mk b/ttcn/LibXsd/module.mk new file mode 100644 index 0000000..edc3ade --- /dev/null +++ b/ttcn/LibXsd/module.mk @@ -0,0 +1,3 @@ +sources := \ + ttcn/UsefulTtcn3Types.ttcn \ + ttcn/XSD.ttcn diff --git a/ttcn/LibXsd/ttcn/UsefulTtcn3Types.ttcn b/ttcn/LibXsd/ttcn/UsefulTtcn3Types.ttcn new file mode 100644 index 0000000..ae682d6 --- /dev/null +++ b/ttcn/LibXsd/ttcn/UsefulTtcn3Types.ttcn @@ -0,0 +1,95 @@ +/******************************************************************************* +* Copyright (c) 2000-2022 Ericsson Telecom AB +* +* XSD to TTCN-3 Translator version: CRL 113 200/6 R6B +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v2.0 +* which accompanies this distribution, and is available at +* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html +*******************************************************************************/ +// +// File: UsefulTtcn3Types.ttcn +// Description: +// References: +// Rev: +// Prodnr: +// Updated: +// Contact: http://ttcn.ericsson.se +// +//////////////////////////////////////////////////////////////////////////////// +module UsefulTtcn3Types { + + + type integer byte (-128 .. 127) /*with { variant "8 bit" }*/; + + type integer unsignedbyte (0 .. 255) /*with { variant "unsigned 8 bit" }*/; + + type integer short (-32768 .. 32767) /*with { variant "16 bit" }*/; + + type integer unsignedshort (0 .. 65535) /*with { variant "unsigned 16 bit" }*/; + + type integer long (-2147483648 .. 2147483647) /*with { variant "32 bit" }*/; + + type integer unsignedlong (0 .. 4294967295) /*with { variant "unsigned 32 bit" }*/; + + type integer longlong ( -9223372036854775808 .. 9223372036854775807 ) /*with { variant "64 bit" }*/; + + type integer unsignedlonglong ( 0 .. 18446744073709551615 ) /*with { variant "unsigned 64 bit" }*/; + + type float IEEE754float /*with { variant "IEEE754 float" }*/; + + type float IEEE754double /*with { variant "IEEE754 double" }*/; + + type float IEEE754extfloat /*with { variant "IEEE754 extended float" }*/; + + type float IEEE754extdouble /*with { variant "IEEE754 extended double" }*/; + + type universal charstring utf8string /*with { variant "UTF-8" }*/; + + type universal charstring bmpstring ( char ( 0,0,0,0 ) .. char ( 0,0,255,255) ) /*with { variant "UCS-2" }*/; + + type universal charstring utf16string ( char ( 0,0,0,0 ) .. char ( 0,16,255,255) ) /*with { variant "UTF-16" }*/; + + type universal charstring iso8859string ( char ( 0,0,0,0 ) .. char ( 0,0,0,255) ) /*with { variant "8 bit" }*/; + + type record IDLfixed + { + unsignedshort digits, + short scale, + charstring value_ + } + /*with { + variant "IDL:fixed FORMAL/01-12-01 v.2.6"; + }*/; + + /* + type charstring char length (1); + + NOTE 1: The name of this useful type is the same as the TTCN-3 keyword used to denote universal + charstring values in the quadraple form. In general it is disallowed to use TTCN-3 keywords as + identifiers. The "char" useful type is a solitary exception and allowed only for backward compatibility + with previous versions of the TTCN-3 standard. (except Titan doesn't) + + NOTE 2: The special string "8 bit" defined in clause 28.2.3 may be used with this type to specify a given encoding + for its values. Also, other properties of the base type can be changed by using attribute mechanisms. + */ + + type universal charstring uchar length (1); + + /* + NOTE: Special strings defined in clause 28.2.3 except "8 bit" may be used with this type to specify a given + encoding for its values. Also, other properties of the base type can be changed by using attribute + mechanisms. + */ + + type bitstring bit length (1); + + type hexstring hex length (1); + + type octetstring octet length (1); + +} +with { +encode "XML"; +} diff --git a/ttcn/LibXsd/ttcn/XSD.ttcn b/ttcn/LibXsd/ttcn/XSD.ttcn new file mode 100644 index 0000000..b519f6b --- /dev/null +++ b/ttcn/LibXsd/ttcn/XSD.ttcn @@ -0,0 +1,338 @@ +/******************************************************************************* +* Copyright (c) 2000-2022 Ericsson Telecom AB +* +* XSD to TTCN-3 Translator version: CRL 113 200/6 R6B +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v2.0 +* which accompanies this distribution, and is available at +* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html +*******************************************************************************/ +// +// File: XSD.ttcn +// Description: +// References: +// Rev: +// Prodnr: +// Updated: +// Contact: http://ttcn.ericsson.se +// +//////////////////////////////////////////////////////////////////////////////// +module XSD { + +import from UsefulTtcn3Types all; + +//These constants are used in the XSD date/time type definitions +const charstring + dash := "-", + cln := ":", + year := "[0-9]#4", + yearExpansion := "(-([1-9][0-9]#(0,))#(,1))#(,1)", + month := "(0[1-9]|1[0-2])", + dayOfMonth := "(0[1-9]|[12][0-9]|3[01])", + hour := "([01][0-9]|2[0-3])", + minute := "([0-5][0-9])", + second := "([0-5][0-9])", + sFraction := "(.[0-9]#(1,))#(,1)", + endOfDayExt := "24:00:00(.0#(1,))#(,1)", + nums := "[0-9]#(1,)", + ZorTimeZoneExt := "(Z|[+-]((0[0-9]|1[0-3]):[0-5][0-9]|14:00))#(,1)", + durTime := "(T[0-9]#(1,)"& + "(H([0-9]#(1,)(M([0-9]#(1,)(S|.[0-9]#(1,)S))#(,1)|.[0-9]#(1,)S|S))#(,1)|"& + "M([0-9]#(1,)(S|.[0-9]#(1,)S)|.[0-9]#(1,)M)#(,1)|"& + "S|"& + ".[0-9]#(1,)S))" + +//anySimpleType + +type XMLCompatibleString AnySimpleType +with { +variant "XSD:anySimpleType"; +}; + +//anyType; + +type record AnyType +{ + record of String embed_values optional, + record of String attr optional, + record of String elem_list +} +with { +variant "XSD:anyType"; +variant "embedValues"; +variant (attr) "anyAttributes"; +variant (elem_list) "anyElement"; +}; +// String types + +type XMLCompatibleString String +with { +variant "XSD:string"; +}; + +type XMLStringWithNoCRLFHT NormalizedString +with { +variant "XSD:normalizedString"; +}; + +type NormalizedString Token +with { +variant "XSD:token"; +}; + +type XMLStringWithNoWhitespace Name +with { +variant "XSD:Name"; +}; + +type XMLStringWithNoWhitespace NMTOKEN +with { +variant "XSD:NMTOKEN"; +}; + +type Name NCName +with { +variant "XSD:NCName"; +}; + +type NCName ID +with { +variant "XSD:ID"; +}; + +type NCName IDREF +with { +variant "XSD:IDREF"; +}; + +type NCName ENTITY +with { +variant "XSD:ENTITY"; +}; + +type octetstring HexBinary +with { +variant "XSD:hexBinary"; +}; + +type octetstring Base64Binary +with { +variant "XSD:base64Binary"; +}; + +type XMLStringWithNoCRLFHT AnyURI +with { +variant "XSD:anyURI"; +}; + +type charstring Language (pattern "[a-zA-Z]#(1,8)(-\w#(1,8))#(0,)") +with { +variant "XSD:language"; +}; +// Integer types + +type integer Integer +with { +variant "XSD:integer"; +}; + +type integer PositiveInteger (1 .. infinity) +with { +variant "XSD:positiveInteger"; +}; + +type integer NonPositiveInteger (-infinity .. 0) +with { +variant "XSD:nonPositiveInteger"; +}; + +type integer NegativeInteger (-infinity .. -1) +with { +variant "XSD:negativeInteger"; +}; + +type integer NonNegativeInteger (0 .. infinity) +with { +variant "XSD:nonNegativeInteger"; +}; + +type longlong Long +with { +variant "XSD:long"; +}; + +type unsignedlonglong UnsignedLong +with { +variant "XSD:unsignedLong"; +}; + +type long Int +with { +variant "XSD:int"; +}; + +type unsignedlong UnsignedInt +with { +variant "XSD:unsignedInt"; +}; + +type short Short +with { +variant "XSD:short"; +}; + +type unsignedshort UnsignedShort +with { +variant "XSD:unsignedShort"; +}; + +type octetstring byte length(1) with {encode "length(1)"}; +type byte Byte +with { +variant "XSD:byte"; +}; + +type unsignedbyte UnsignedByte +with { +variant "XSD:unsignedByte"; +}; + +// Float types + +type float Decimal +with { +variant "XSD:decimal"; +}; + +type IEEE754float Float +with { +variant "XSD:float"; +}; + +type IEEE754double Double +with { +variant "XSD:double"; +}; + +// Time types + +type charstring Duration (pattern + "{dash}#(,1)P({nums}(Y({nums}(M({nums}D{durTime}#(,1)|{durTime}#(,1))|D{durTime}#(,1))|" & + "{durTime}#(,1))|M({nums}D{durTime}#(,1)|{durTime}#(,1))|D{durTime}#(,1))|{durTime})") +with { +variant "XSD:duration"; +}; + +type charstring DateTime (pattern + "{yearExpansion}{year}{dash}{month}{dash}{dayOfMonth}T({hour}{cln}{minute}{cln}{second}" & + "{sFraction}|{endOfDayExt}){ZorTimeZoneExt}" ) +with { +variant "XSD:dateTime"; +}; + +type charstring Time (pattern + "({hour}{cln}{minute}{cln}{second}{sFraction}|{endOfDayExt}){ZorTimeZoneExt}" ) +with { +variant "XSD:time"; +}; + +type charstring Date (pattern + "{yearExpansion}{year}{dash}{month}{dash}{dayOfMonth}{ZorTimeZoneExt}" ) +with { +variant "XSD:date"; +}; + +type charstring GYearMonth (pattern + "{yearExpansion}{year}{dash}{month}{ZorTimeZoneExt}" ) +with { +variant "XSD:gYearMonth"; +}; + +type charstring GYear (pattern + "{yearExpansion}{year}{ZorTimeZoneExt}" ) +with { +variant "XSD:gYear"; +}; + +type charstring GMonthDay (pattern + "{dash}{dash}{month}{dash}{dayOfMonth}{ZorTimeZoneExt}" ) +with { +variant "XSD:gMonthDay"; +}; + +type charstring GDay (pattern + "{dash}{dash}{dash}{dayOfMonth}{ZorTimeZoneExt}" ) +with { +variant "XSD:gDay"; +}; + +type charstring GMonth (pattern + "{dash}{dash}{month}{ZorTimeZoneExt}" ) +with { +variant "XSD:gMonth"; +}; + +// Sequence types + +type record of NMTOKEN NMTOKENS +with { +variant "XSD:NMTOKENS"; +}; + +type record of IDREF IDREFS +with { +variant "XSD:IDREFS"; +}; + +type record of ENTITY ENTITIES +with { +variant "XSD:ENTITIES"; +}; + +type record QName +{ + AnyURI uri optional, + NCName name +} +with { +variant "XSD:QName"; +}; + +// Boolean type + +type boolean Boolean +with { +variant "XSD:boolean"; +}; + +//TTCN-3 type definitions supporting the mapping of W3C XML Schema built-in datatypes + +type utf8string XMLCompatibleString +( + char(0,0,0,9)..char(0,0,0,9), + char(0,0,0,10)..char(0,0,0,10), + char(0,0,0,13)..char(0,0,0,13), + char(0,0,0,32)..char(0,0,215,255), + char(0,0,224,0)..char(0,0,255,253), + char(0,1,0,0)..char(0,16,255,253) +) + +type utf8string XMLStringWithNoWhitespace +( + char(0,0,0,33)..char(0,0,215,255), + char(0,0,224,0)..char(0,0,255,253), + char(0,1,0,0)..char(0,16,255,253) +) + +type utf8string XMLStringWithNoCRLFHT +( + char(0,0,0,32)..char(0,0,215,255), + char(0,0,224,0)..char(0,0,255,253), + char(0,1,0,0)..char(0,16,255,253) +) + +} +with{ +encode "XML" +} -- GitLab From bafc335bf71b976a49fb9edd4237fc517d872834 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Tue, 8 Nov 2022 09:50:12 +0100 Subject: [PATCH 05/37] Remove linked file module.mk --- ttcn/LibHttp/module.mk | 1 - 1 file changed, 1 deletion(-) delete mode 120000 ttcn/LibHttp/module.mk diff --git a/ttcn/LibHttp/module.mk b/ttcn/LibHttp/module.mk deleted file mode 120000 index 26de716..0000000 --- a/ttcn/LibHttp/module.mk +++ /dev/null @@ -1 +0,0 @@ -module_cise.mk \ No newline at end of file -- GitLab From 3da139f68809ee8a27fc16f042db9c055da0939b Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Mon, 14 Nov 2022 16:23:03 +0100 Subject: [PATCH 06/37] Remove useless files --- ccsrc/Framework/include/oer_codec.hh | 48 ------------------------- ccsrc/Framework/include/per_codec.hh | 50 -------------------------- ccsrc/Framework/include/per_codec.t.hh | 26 -------------- 3 files changed, 124 deletions(-) delete mode 100644 ccsrc/Framework/include/oer_codec.hh delete mode 100644 ccsrc/Framework/include/per_codec.hh delete mode 100644 ccsrc/Framework/include/per_codec.t.hh diff --git a/ccsrc/Framework/include/oer_codec.hh b/ccsrc/Framework/include/oer_codec.hh deleted file mode 100644 index 51a32cd..0000000 --- a/ccsrc/Framework/include/oer_codec.hh +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include "params.hh" - -class OCTETSTRING; -class CHARSTRING; -class BITSTRING; - -struct asn_TYPE_descriptor_s; -class asn1_recode_oer { -protected: - int xer2oer(const asn_TYPE_descriptor_s &td, TTCN_Buffer &buf); - int oer2xer(const asn_TYPE_descriptor_s &td, TTCN_Buffer &buf); - int recode(const asn_TYPE_descriptor_s &td, int from, int to, TTCN_Buffer &buf); -}; - -template class oer_codec : public asn1_recode_oer { -public: - virtual int encode(const TPDU &msg, BITSTRING &bits) = 0; - virtual int decode(const BITSTRING &bits, TPDU &msg) = 0; - -protected: - inline int _decode(const TTCN_Typedescriptor_t &ttcn, const asn_TYPE_descriptor_s &td, const BITSTRING &p_data, TPDU &msg) { - TTCN_Buffer buf(bit2oct(p_data)); - TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING); - int rc = oer2xer(td, buf); - if (rc > 0) { - msg.decode(ttcn, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL); - rc = buf.get_len(); - } - return rc; - } - inline int _encode(const TTCN_Typedescriptor_t &ttcn, const asn_TYPE_descriptor_s &td, const TPDU &msg, BITSTRING &p_data) { - int rc = -1; - TTCN_Buffer buf; - TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING); - msg.encode(ttcn, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER); - if (buf.get_len() > 0) { - rc = xer2oer(td, buf); - if (rc > 0) { - p_data = oct2bit(OCTETSTRING(buf.get_len(), buf.get_data())); - } - } - return rc; - } -}; - -#endif diff --git a/ccsrc/Framework/include/per_codec.hh b/ccsrc/Framework/include/per_codec.hh deleted file mode 100644 index 077d74a..0000000 --- a/ccsrc/Framework/include/per_codec.hh +++ /dev/null @@ -1,50 +0,0 @@ -/*! - * \file per_codec.hh - * \brief Header file for TITAN message to ASN.1 PER message codec. - * \author ETSI STF525 - * \copyright ETSI Copyright Notification - * No part may be reproduced except as authorized by written permission. - * The copyright and the foregoing restriction extend to reproduction in all media. - * All rights reserved. - * \version 0.1 - */ -#pragma once - -#include "asn1_recode_per.hh" -#include "params.hh" - -class BITSTRING; //! Forward declaration of TITAN class -class TTCN_Typedescriptor_t; //! Forward declaration of TITAN class - -struct asn_TYPE_descriptor_s; //! Declare asn1c class - -/*! - * \class per_codec - * \brief This class provides the interface for all ASN.1 PER codecs. - * \remark This class uses asn1c external tool - */ -template class per_codec : public asn1_recode_per { -public: //! \publicsection - /*! - * \fn int encode(const TPDU& p_message, BITSTRING& p_bitstring); - * \brief Encode TITAN message into ASN.1 PER message - * \param[in] p_message The PDU message to encode - * \param[out] p_bitstring The encoded PDU message in bit string format - * \pure - */ - virtual int encode(const TPDU &p_message, BITSTRING &p_bitstring) = 0; - /*! - * \fn int decode(const BITSTRING& p_bitstring, TPDU& p_message); - * \brief Decode ASN.1 PER message into TITAN message - * \param[in] p_bitstring The network message in bit string format to decode - * \param[out] p_message The PDU message - * \pure - */ - virtual int decode(const BITSTRING &p_bitstring, TPDU &p_message) = 0; - -protected: //! \protectedsection - int _decode(const TTCN_Typedescriptor_t &ttcn, const asn_TYPE_descriptor_s &td, const BITSTRING &p_data, TPDU &msg); - int _encode(const TTCN_Typedescriptor_t &ttcn, const asn_TYPE_descriptor_s &td, const TPDU &msg, BITSTRING &p_data); -}; // End of class per_codec - -#include "per_codec.t.hh" diff --git a/ccsrc/Framework/include/per_codec.t.hh b/ccsrc/Framework/include/per_codec.t.hh deleted file mode 100644 index 6973dc6..0000000 --- a/ccsrc/Framework/include/per_codec.t.hh +++ /dev/null @@ -1,26 +0,0 @@ -#include - -template int per_codec::_decode(const TTCN_Typedescriptor_t &ttcn, const asn_TYPE_descriptor_s &td, const BITSTRING &p_data, TPDU &msg) { - TTCN_Buffer buf(bit2oct(p_data)); - TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING); - int rc = per2ber(td, buf); - if (rc > 0) { - msg.decode(ttcn, buf, TTCN_EncDec::CT_BER, BER_ACCEPT_ALL); - rc = buf.get_len(); - } - return rc; -} - -template int per_codec::_encode(const TTCN_Typedescriptor_t &ttcn, const asn_TYPE_descriptor_s &td, const TPDU &msg, BITSTRING &p_data) { - int rc = -1; - TTCN_Buffer buf; - TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING); - msg.encode(ttcn, buf, TTCN_EncDec::CT_BER, BER_ENCODE_DER); - if (buf.get_len() > 0) { - rc = ber2per(td, buf); - if (rc > 0) { - p_data = oct2bit(OCTETSTRING(buf.get_len(), buf.get_data())); - } - } - return rc; -} -- GitLab From 683ea737b145b03518cbe462485fe7bee3a858b6 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Mon, 14 Nov 2022 16:25:55 +0100 Subject: [PATCH 07/37] Add common XML support --- ccsrc/Framework/include/base_time.hh | 2 +- ccsrc/Framework/src/base_time.cc | 2 +- ccsrc/Helpers/helpers_externals.cc | 35 +- ccsrc/Protocols/Http/http_codec.cc | 1368 ++++++++--------- ccsrc/Protocols/Xml/include/xml_converters.hh | 43 + ccsrc/Protocols/Xml/module.mk | 4 + ccsrc/Protocols/Xml/src/xml_converters.cc | 62 + .../LibHelpers/ttcn/LibHelpers_Functions.ttcn | 12 + 8 files changed, 840 insertions(+), 688 deletions(-) create mode 100644 ccsrc/Protocols/Xml/include/xml_converters.hh create mode 100644 ccsrc/Protocols/Xml/module.mk create mode 100644 ccsrc/Protocols/Xml/src/xml_converters.cc diff --git a/ccsrc/Framework/include/base_time.hh b/ccsrc/Framework/include/base_time.hh index 03fa8f6..ae67b57 100644 --- a/ccsrc/Framework/include/base_time.hh +++ b/ccsrc/Framework/include/base_time.hh @@ -1,6 +1,6 @@ /*! * \file base_time.hh - * \brief Header file for the control port base_time functionality. + * \brief Header file for base_time functionality. * \author ETSI STF525 * \copyright ETSI Copyright Notification * No part may be reproduced except as authorized by written permission. diff --git a/ccsrc/Framework/src/base_time.cc b/ccsrc/Framework/src/base_time.cc index 3833119..28c2cc6 100644 --- a/ccsrc/Framework/src/base_time.cc +++ b/ccsrc/Framework/src/base_time.cc @@ -1,6 +1,6 @@ /*! * \file base_time.cc - * \brief Source file for the control port base_time functionality. + * \brief Source file base_time functionality. * \author ETSI STF525 * \copyright ETSI Copyright Notification * No part may be reproduced except as authorized by written permission. diff --git a/ccsrc/Helpers/helpers_externals.cc b/ccsrc/Helpers/helpers_externals.cc index b387292..fd75828 100644 --- a/ccsrc/Helpers/helpers_externals.cc +++ b/ccsrc/Helpers/helpers_externals.cc @@ -2,6 +2,7 @@ #include #include "base_time.hh" +#include "converter.hh" #include "loggers.hh" #ifndef M_PI @@ -29,7 +30,7 @@ namespace LibHelpers__Functions { * @see function f_getMinuteOfTheYear() return MinuteOfTheYear */ INTEGER fx__getMinuteOfTheYear() { - // TODO: this is just a sceleton. fill in the function + // TODO: this is just a skeleton. fill in the function return 0; } @@ -39,8 +40,38 @@ namespace LibHelpers__Functions { * @see function f_getDSecond() return DSecond */ INTEGER fx__getDSecond() { - // TODO: this is just a sceleton. fill in the function + // TODO: this is just a skeleton. fill in the function return 0; } + /** + * @desc Encode into Base64 + * @return p_to_encode - The buffer to be encoded + * @see function f_enc_base64(in octetstring p_to_encode) return octetstring + */ + OCTETSTRING fx__enc__base64(const OCTETSTRING& p_to_encode) { + loggers::get_instance().log_msg(">>> fx__enc__base64: ", p_to_encode); + + const std::vector to_encode(static_cast(p_to_encode), static_cast(p_to_encode) + p_to_encode.lengthof()); + std::vector b64 = converter::get_instance().buffer_to_base64(to_encode); + OCTETSTRING os(b64.size(), b64.data()); + loggers::get_instance().log_msg("<<< fx__enc__base64: ", os); + return os; + } + + /** + * @desc Decode from Base64 + * @return p_to_decode - The buffer to be decoded + * @see function f_dec_base64(in octetstring p_to_decode) return octetstring + */ + OCTETSTRING fx__dec__base64(const OCTETSTRING& p_to_decode) { + loggers::get_instance().log_msg(">>> fx__dec__base64: ", p_to_decode); + + const std::vector to_decode(static_cast(p_to_decode), static_cast(p_to_decode) + p_to_decode.lengthof()); + std::vector b64 = converter::get_instance().base64_to_buffer(to_decode); + OCTETSTRING os(b64.size(), b64.data()); + loggers::get_instance().log_msg("<<< fx__dec__base64: ", os); + return os; + } + } // namespace LibHelpers__Functions diff --git a/ccsrc/Protocols/Http/http_codec.cc b/ccsrc/Protocols/Http/http_codec.cc index 8322769..a5818f1 100644 --- a/ccsrc/Protocols/Http/http_codec.cc +++ b/ccsrc/Protocols/Http/http_codec.cc @@ -1,684 +1,684 @@ -#include -#include -#include - -#include "codec_stack_builder.hh" - -#include "http_codec.hh" - -#include "loggers.hh" - -#include "LibHttp_TypesAndValues.hh" -#include "LibHttp_MessageBodyTypes.hh" -#include "LibHttp_XmlMessageBodyTypes.hh" -#include "LibHttp_JsonMessageBodyTypes.hh" - -int http_codec::encode(const LibHttp__TypesAndValues::HttpMessage &msg, OCTETSTRING &data) { - loggers::get_instance().log_msg(">>> http_codec::encode: ", (const Base_Type &)msg); - loggers::get_instance().log(">>> http_codec::encode: %p", this); - - TTCN_EncDec::clear_error(); - TTCN_Buffer encoding_buffer; - - _ec.reset(); - - int result; - if (msg.ischosen(LibHttp__TypesAndValues::HttpMessage::ALT_request)) { - result = encode_request(msg.request(), encoding_buffer); - } else if (msg.ischosen(LibHttp__TypesAndValues::HttpMessage::ALT_response)) { - result = encode_response(msg.response(), encoding_buffer); - } else { - loggers::get_instance().warning("http_codec::encode: Unbound HttpMessage"); - return -1; - } - - data = OCTETSTRING(encoding_buffer.get_len(), encoding_buffer.get_data()); - - loggers::get_instance().log_msg("<<< http_codec::encode: data=", data); - return result; -} - -int http_codec::decode(const OCTETSTRING &data, LibHttp__TypesAndValues::HttpMessage &msg, params *params) { - loggers::get_instance().log_msg(">>> http_codec::decode: data=", data); - - // Sanity checks - if ((data[0].get_octet() & 0x80) == 0x80) { - loggers::get_instance().warning("http_codec::decode: Unicode format not supported"); - return -1; - } - - TTCN_EncDec::clear_error(); - TTCN_Buffer decoding_buffer(data); - loggers::get_instance().log_to_hexa("http_codec::decode: decoding_buffer=", decoding_buffer); - - _dc.reset(); - - _params = params; - - // Get the first line (e.g. HTTP/1.1 302 Found or POST / HTTP/1.1) - CHARSTRING message_id; - if (get_line(decoding_buffer, message_id) == -1) { - loggers::get_instance().warning("http_codec::decode: get_line failed, errno: %d", errno); - return -1; - } - loggers::get_instance().log_msg("http_codec::decode: message_id: ", message_id); - // Extract parameters - try { - std::string str(static_cast(message_id)); - std::regex rgx("\\s*(\\w+)/"); - std::sregex_iterator begin(str.cbegin(), str.cend(), rgx); - std::smatch m = *begin; - loggers::get_instance().log("http_codec::decode: %d - %s", m.size(), m[0].str().c_str()); - if (m[0].str().compare("HTTP/") == 0) { // HTTP response - LibHttp__TypesAndValues::Response response; - std::regex rgx("\\s*HTTP/(\\d+)\\.(\\d+)\\s+(\\d+)\\s+([\\w\\s\\t\\v\\f]+)*"); - std::sregex_iterator begin(str.cbegin(), str.cend(), rgx); - std::smatch m = *begin; - loggers::get_instance().log("http_codec::decode: Process response: %d", m.size()); - if (m.size() != 5) { - loggers::get_instance().warning("http_codec::decode: Unsupported tag"); - return -1; - } - response.version__major() = std::stoi(m[1].str().c_str()); - response.version__minor() = std::stoi(m[2].str().c_str()); - response.statuscode() = std::stoi(m[3].str().c_str()); - response.statustext() = CHARSTRING(m[4].str().c_str()); - LibHttp__TypesAndValues::Headers headers; - std::string content_type; - decode_headers(decoding_buffer, headers, content_type); - response.header() = headers; - loggers::get_instance().log_to_hexa("Before decoding Body: ", decoding_buffer); - LibHttp__MessageBodyTypes::HttpMessageBody body; - if (decode_body(decoding_buffer, body, content_type) == -1) { - response.body().set_to_omit(); - } else { - response.body() = OPTIONAL(body); - } - // Add lower layers parameters - loggers::get_instance().log("http_codec::decode: Add lower layers parameters"); - params->log(); - params::const_iterator it = params->find(params::use_ssl); - if (it != params->cend()) { - loggers::get_instance().log("http_codec::receive_data: tls=%s", it->second.c_str()); - response.tls() = (it->second.compare("1") == 0) ? true : false; - } else { - response.tls().set_to_omit(); - } - it = params->find(params::mutual_auth); - if (it != params->cend()) { - loggers::get_instance().log("http_codec::receive_data: mutual_tls=%s", it->second.c_str()); - response.mutual__tls() = (it->second.compare("1") == 0) ? true : false; - } else { - response.mutual__tls().set_to_omit(); - } - msg.response() = response; - } else { // HTTP request - LibHttp__TypesAndValues::Request request; - std::regex rgx("\\s*(\\w+)\\s+(.+)\\s+HTTP/(\\d)\\.(\\d)"); - std::sregex_iterator begin(str.cbegin(), str.cend(), rgx); - std::smatch m = *begin; - if (m.size() != 5) { - loggers::get_instance().error("http_codec::decode: Unsupported tag"); - return -1; - } - request.method() = CHARSTRING(m[1].str().c_str()); - request.uri() = CHARSTRING(m[2].str().c_str()); - request.version__major() = std::stoi(m[3].str().c_str()); - request.version__minor() = std::stoi(m[4].str().c_str()); - LibHttp__TypesAndValues::Headers headers; - std::string content_type; - decode_headers(decoding_buffer, headers, content_type); - request.header() = headers; - OPTIONAL body; - body.set_to_omit(); - if (decode_body(decoding_buffer, body, content_type) == -1) { - request.body().set_to_omit(); - } else { - request.body() = body; - } - msg.request() = request; - } - - loggers::get_instance().log_msg("<<< http_codec::decode: ", (const Base_Type &)msg); - return 0; - } catch (const std::logic_error &e) { - return -1; - } -} - -int http_codec::encode_request(const LibHttp__TypesAndValues::Request &p_request, TTCN_Buffer &p_encoding_buffer) { - loggers::get_instance().log_msg(">>> http_codec::encode_request: ", (const Base_Type &)p_request); - - // Encode generic part - p_encoding_buffer.put_cs(p_request.method()); - p_encoding_buffer.put_c(' '); - p_encoding_buffer.put_cs(p_request.uri()); - p_encoding_buffer.put_cs(" HTTP/"); - p_encoding_buffer.put_cs(int2str(p_request.version__major())); - p_encoding_buffer.put_c('.'); - p_encoding_buffer.put_cs(int2str(p_request.version__minor())); - p_encoding_buffer.put_cs("\r\n"); - - // Encode headers excepeted the Content-Length - const LibHttp__TypesAndValues::Headers &headers = p_request.header(); - std::string content_type; - for (int i = 0; i < headers.size_of(); i++) { - const LibHttp__TypesAndValues::Header &header = headers[i]; - loggers::get_instance().log_msg("http_codec::encode_request: Processing header ", header.header__name()); - if (std::string(static_cast(header.header__name())).compare("Content-Length") == 0) { // Skip it, processed later - loggers::get_instance().log("http_codec::encode_request: Skip it"); - continue; - } else { - p_encoding_buffer.put_cs(header.header__name()); - p_encoding_buffer.put_cs(": "); - const OPTIONAL &o = header.header__value(); - if (o.ispresent()) { - const LibHttp__TypesAndValues::charstring__list &v = dynamic_cast &>(o); - if (v.size_of() > 0) { - loggers::get_instance().log_msg("http_codec::encode_request: Processing value ", v[0]); - if (std::string(static_cast(header.header__name())).compare("Content-Type") == 0) { // Store it for HTTP body payload encoding - loggers::get_instance().log("http_codec::encode_request: Storing Content-Type"); - int j = 0; - while (j < v.size_of()) { - content_type += v[j++]; - } // End of 'while' statement - } - p_encoding_buffer.put_cs(v[0]); - int j = 1; - while (j < v.size_of()) { - p_encoding_buffer.put_cs(", "); - loggers::get_instance().log_msg("http_codec::encode_request: Processing value ", v[j]); - p_encoding_buffer.put_cs(v[j++]); - } // End of 'while' statement - } - } // else, do not include it - } - p_encoding_buffer.put_cs("\r\n"); - } // End of 'for' statement - - // Encode message body - const OPTIONAL &v = p_request.body(); - OCTETSTRING os; - if (v.ispresent()) { - const LibHttp__MessageBodyTypes::HttpMessageBody &body = static_cast(*v.get_opt_value()); - loggers::get_instance().log_msg("http_codec::encode_request: body: ", body); - if (encode_body(body, os, content_type) == -1) { - loggers::get_instance().warning("http_codec::encode_request: Failed to encode HTTP body"); - _ec.length = 0; - _ec.is_content_length_present = 0x00; - } else { - _ec.length = os.lengthof(); - _ec.is_content_length_present = 0x01; - } - loggers::get_instance().log("http_codec::encode_request: length=%d", _ec.length); - } else { - loggers::get_instance().log("http_codec::encode_request: HTTP body field not present"); - _ec.length = 0; - _ec.is_content_length_present = 0x00; - } - - // Encode Content-Length header - p_encoding_buffer.put_cs("Content-Length: "); - if (_ec.length != 0) { - loggers::get_instance().log("http_codec::encode_request: Content-Length: %s", - static_cast(int2str(_ec.length + 2 /*Stand for the last CRLF*/))); - p_encoding_buffer.put_cs(static_cast(int2str(_ec.length))); - _ec.is_content_length_present = 0x01; - } else { - p_encoding_buffer.put_cs("0"); - _ec.is_content_length_present = 0x00; - } - loggers::get_instance().log("http_codec::encode_request: Content-Length: %d - %x", _ec.length, _ec.is_content_length_present); - p_encoding_buffer.put_cs("\r\n"); - - // Add message body - p_encoding_buffer.put_cs("\r\n"); - if (_ec.is_content_length_present == 0x01) { - loggers::get_instance().log_msg("http_codec::encode_request: Add body ", os); - p_encoding_buffer.put_os(os); - // p_encoding_buffer.put_cs("\r\n"); - } - - loggers::get_instance().log_to_hexa("<<< http_codec::encode_request: ", p_encoding_buffer); - return 0; -} - -int http_codec::encode_response(const LibHttp__TypesAndValues::Response &p_response, TTCN_Buffer &p_encoding_buffer) { - loggers::get_instance().log_msg(">>> http_codec::encode_response: ", (const Base_Type &)p_response); - - // Encode generic part - p_encoding_buffer.put_cs("HTTP/"); - p_encoding_buffer.put_cs(int2str(p_response.version__major())); - p_encoding_buffer.put_c('.'); - p_encoding_buffer.put_cs(int2str(p_response.version__minor())); - p_encoding_buffer.put_cs(" "); - p_encoding_buffer.put_cs(int2str(p_response.statuscode())); - p_encoding_buffer.put_cs(" "); - if (p_response.statustext().lengthof() != 0) { - p_encoding_buffer.put_cs(p_response.statustext()); - } - p_encoding_buffer.put_cs("\r\n"); - - // Encode headers excepeted the Content-Length - const LibHttp__TypesAndValues::Headers &headers = p_response.header(); - std::string content_type; - for (int i = 0; i < headers.size_of(); i++) { - const LibHttp__TypesAndValues::Header &header = headers[i]; - loggers::get_instance().log_msg("http_codec::encode_response: Processing header ", header.header__name()); - if (std::string(static_cast(header.header__name())).compare("Content-Length") == 0) { - continue; - } else { - p_encoding_buffer.put_cs(header.header__name()); - p_encoding_buffer.put_cs(": "); - const OPTIONAL &o = header.header__value(); - if (o.ispresent()) { - const LibHttp__TypesAndValues::charstring__list &v = dynamic_cast &>(o); - if (v.size_of() > 0) { - loggers::get_instance().log_msg("http_codec::encode_response: Processing value ", v[0]); - if (std::string(static_cast(header.header__name())).compare("Content-Type") == 0) { // Store it for HTTP body payload encoding - loggers::get_instance().log("http_codec::encode_response: Storing Content-Type"); - int j = 0; - while (j < v.size_of()) { - content_type += v[j++]; - } // End of 'while' statement - } - p_encoding_buffer.put_cs(v[0]); - int j = 1; - while (j < v.size_of()) { - p_encoding_buffer.put_cs(", "); - loggers::get_instance().log_msg("http_codec::encode_response: Processing value ", v[j]); - p_encoding_buffer.put_cs(v[j++]); - j += 1; - } // End of 'while' statement - } - } // else, do not include it - } - p_encoding_buffer.put_cs("\r\n"); - } // End of 'for' statement - - // Encode message body - const OPTIONAL &v = p_response.body(); - OCTETSTRING os; - if (v.ispresent()) { - const LibHttp__MessageBodyTypes::HttpMessageBody &body = static_cast(*v.get_opt_value()); - loggers::get_instance().log_msg("http_codec::encode_response: body: ", body); - if (encode_body(body, os, content_type) == -1) { - _ec.length = 0; - _ec.is_content_length_present = 0x00; - } else { - _ec.length = os.lengthof(); - _ec.is_content_length_present = 0x01; - } - loggers::get_instance().log("http_codec::encode_response: length=%d", _ec.length); - } else { - loggers::get_instance().log("http_codec::encode_response: HTTP body field not present"); - _ec.length = 0; - _ec.is_content_length_present = 0x00; - } - - // Encode Content-Length header - p_encoding_buffer.put_cs("Content-Length: "); - if (_ec.length != 0) { - loggers::get_instance().log("http_codec::encode_request: Content-Length: %s", - static_cast(int2str(_ec.length + 2 /*Stand for the last CRLF*/))); - p_encoding_buffer.put_cs(static_cast(int2str(_ec.length))); - _ec.is_content_length_present = 0x01; - } else { - p_encoding_buffer.put_cs("0"); - _ec.is_content_length_present = 0x00; - } - loggers::get_instance().log("http_codec::encode_request: Content-Length: %d - %x", _ec.length, _ec.is_content_length_present); - p_encoding_buffer.put_cs("\r\n"); - - // Add message body - p_encoding_buffer.put_cs("\r\n"); - if (_ec.is_content_length_present == 0x01) { - loggers::get_instance().log_msg("http_codec::encode_request: Add body ", os); - p_encoding_buffer.put_os(os); - // p_encoding_buffer.put_cs("\r\n"); - } - - loggers::get_instance().log_to_hexa("<<< http_codec::encode_response: ", p_encoding_buffer); - return 0; -} - -int http_codec::decode_headers(TTCN_Buffer &decoding_buffer, LibHttp__TypesAndValues::Headers &headers, std::string &p_content_type) { - loggers::get_instance().log(">>> http_codec::decode_headers"); - loggers::get_instance().log_to_hexa("http_codec::decode_headers: ", decoding_buffer); - - CHARSTRING cstr; - int i = 0; - while (true) { - switch (get_line(decoding_buffer, cstr, true)) { - case 0: { - loggers::get_instance().log_msg("http_codec::decode_headers: ", cstr); - LibHttp__TypesAndValues::Header header; - if (decode_header(cstr, header) == -1) { - loggers::get_instance().warning("http_codec::decode_headers: Failed to decode header %s", static_cast(cstr)); - return -1; - } - headers[i++] = header; - if (std::string(static_cast(header.header__name())).compare("Content-Type") == 0) { - if (header.header__value().is_present() != 0) { - const PreGenRecordOf::PREGEN__RECORD__OF__CHARSTRING &l = - static_cast(*header.header__value().get_opt_value()); - p_content_type = static_cast(l[0]); - } else { - p_content_type = ""; - } - } - } break; - case 1: - if (headers.is_bound()) { - loggers::get_instance().log_msg("<<< http_codec::decode_headers: ", headers); - return 0; - } else { - loggers::get_instance().warning("http_codec::decode_headers: Failed to decode headers"); - return -1; - } - case -1: - loggers::get_instance().warning("http_codec::decode_headers: Failed to decode headers"); - return -1; - } // End of 'switch' statement - } // End of 'while' statement -} - -int http_codec::decode_header(CHARSTRING &header_line, LibHttp__TypesAndValues::Header &header) { - loggers::get_instance().log_msg(">>> http_codec::decode_header", header_line); - - try { - std::string str(static_cast(header_line)); - std::regex rgx("([0-9a-zA-Z-]+)\\:\\s+(.+)(,(.+))*"); - std::sregex_iterator begin(str.cbegin(), str.cend(), rgx); - std::smatch m = *begin; - if (m.size() < 5) { - loggers::get_instance().warning("http_codec::decode_header: Failed to decode header %s", str.c_str()); - return -1; - } - loggers::get_instance().log("http_codec::decode_header: %d", m.size()); - header.header__name() = CHARSTRING(m[1].str().c_str()); - LibHttp__TypesAndValues::charstring__list v; - for (unsigned int j = 0; j < m.size(); j++) { - if (m[j + 2].str().length() == 0) { - break; - } - v[j] = CHARSTRING(m[j + 2].str().c_str()); - } // End of 'for' statement - header.header__value() = OPTIONAL(v); - - if (m[1].str().compare("Content-Length") == 0) { - // Save the the body length - loggers::get_instance().log("http_codec::decode_header: decoded Content-Length %s", m[2].str().c_str()); - _dc.length = std::stoi(m[2].str()); - } else if (m[1].str().compare("Transfer-Encoding") == 0) { - if (m[2].str().find("chunked") != std::string::npos) { - _dc.chunked = true; - loggers::get_instance().log("http_codec::decode_header: decoded Transfer-Encoding %x", _dc.chunked); - } - } - - return 0; - } catch (const std::logic_error &e) { - return -1; - } -} - -int http_codec::encode_body(const LibHttp__MessageBodyTypes::HttpMessageBody &p_message_body, OCTETSTRING &p_encoding_buffer, - const std::string &p_content_type) { - loggers::get_instance().log_msg(">>> http_codec::encode_body: ", (const Base_Type &)p_message_body); - - // Sanity check - if (p_content_type.empty()) { - loggers::get_instance().warning("http_codec::encode_body: Failed to select a codec for HTTP body payload"); - return -1; - } - - if (p_message_body.ischosen(LibHttp__MessageBodyTypes::HttpMessageBody::ALT_binary__body)) { - const LibHttp__BinaryMessageBodyTypes::BinaryBody &binary_body = p_message_body.binary__body(); - if (binary_body.ischosen(LibHttp__BinaryMessageBodyTypes::BinaryBody::ALT_raw)) { - p_encoding_buffer = OCTETSTRING(binary_body.raw().lengthof(), (unsigned char *)static_cast(binary_body.raw())); - } else { - encode_body_binary(binary_body, p_encoding_buffer, p_content_type); - } - } else if (p_message_body.ischosen(LibHttp__MessageBodyTypes::HttpMessageBody::ALT_json__body)) { - const LibHttp__JsonMessageBodyTypes::JsonBody& json_body = p_message_body.json__body(); - if (json_body.ischosen(LibHttp__JsonMessageBodyTypes::JsonBody::ALT_raw)) { - p_encoding_buffer = unichar2oct(json_body.raw()); - } else { - encode_body_json(json_body, p_encoding_buffer, p_content_type); - } - } else if (p_message_body.ischosen(LibHttp__MessageBodyTypes::HttpMessageBody::ALT_xml__body)) { - const LibHttp__XmlMessageBodyTypes::XmlBody &xml_body = p_message_body.xml__body(); - if (xml_body.ischosen(LibHttp__XmlMessageBodyTypes::XmlBody::ALT_raw)) { - p_encoding_buffer = OCTETSTRING(xml_body.raw().lengthof(), (unsigned char *)static_cast(xml_body.raw())); - } else { - encode_body_xml(xml_body, p_encoding_buffer, p_content_type); - } - } else if (p_message_body.ischosen(LibHttp__MessageBodyTypes::HttpMessageBody::ALT_html__body)) { - p_encoding_buffer = OCTETSTRING(p_message_body.html__body().lengthof(), (unsigned char *)static_cast(p_message_body.html__body())); - } else if (p_message_body.ischosen(LibHttp__MessageBodyTypes::HttpMessageBody::ALT_text__body)) { - p_encoding_buffer = OCTETSTRING(p_message_body.text__body().lengthof(), (unsigned char *)static_cast(p_message_body.text__body())); - } else { - loggers::get_instance().warning("http_codec::encode_body: Failed to encode HTTP message body"); - return -1; - } - loggers::get_instance().log_msg("http_codec::encode_body: HTTP message ", p_encoding_buffer); - _ec.length = p_encoding_buffer.lengthof(); - loggers::get_instance().log("http_codec::encode_body: HTTP message length: %d", _ec.length); - - return 0; -} - -int http_codec::decode_body(TTCN_Buffer &decoding_buffer, LibHttp__MessageBodyTypes::HttpMessageBody &message_body, const std::string &p_content_type) { - loggers::get_instance().log(">>> http_codec::decode_body"); - loggers::get_instance().log_to_hexa("http_codec::decode_body", decoding_buffer); - loggers::get_instance().log("http_codec::decode_body: # of codecs=%d - %p", _codecs.size(), this); - loggers::get_instance().log("http_codec::decode_body: Content-Type=%s", p_content_type.c_str()); - - // Sanity checks - if (decoding_buffer.get_len() - decoding_buffer.get_pos() <= 0) { - return -1; - } - /* TODO Uncomment if (p_content_type.empty()) { - loggers::get_instance().warning("http_codec::encode_body: Failed to select a codec for HTTP body payload"); - return -1; - }*/ - - OCTETSTRING s(decoding_buffer.get_len() - decoding_buffer.get_pos(), decoding_buffer.get_data() + decoding_buffer.get_pos()); - loggers::get_instance().log_msg("http_codec::decode_body: raw body=", s); - - // Align the payload length with the specified Content-Lenght value - loggers::get_instance().log("http_codec::decode_body: _dc.length=%d - body length=%d", _dc.length, s.lengthof()); - OCTETSTRING body; - if (_dc.length != 0) { - const unsigned char *p = static_cast(s); - if ((unsigned int)s.lengthof() <= _dc.length) { - body = OCTETSTRING(s.lengthof(), p); - } else { - body = OCTETSTRING(_dc.length, p); - } - } else { - loggers::get_instance().warning("http_codec::decode_body: No Conten-Length header, process all remaining bytes"); - body = s; - } - loggers::get_instance().log_msg("http_codec::decode_body: Aligned body=", body); - loggers::get_instance().log("http_codec::decode_body: body length=%d", body.lengthof()); - /* TODO To be removed - // Remove CRLF if any - int counter = 0; - if ((body[body.lengthof() - 1].get_octet() == 0x0d) || (body[body.lengthof() - 1].get_octet() == 0x0a)) { - counter += 1; - if ((body[body.lengthof() - 2].get_octet() == 0x0d) || (body[body.lengthof() - 2].get_octet() == 0x0a)) { - counter += 1; - } - } - loggers::get_instance().log("http_codec::decode_body: counter=%d", counter); - body = OCTETSTRING(body.lengthof() - counter, static_cast(body)); - */ - if (_dc.chunked) { - int counter = 0; - int prev = 0; - OCTETSTRING os(0, nullptr); - do { - while (counter < body.lengthof()) { // Extract the size of the chunk \r[\n] - if ((body[counter].get_octet() == '\r') || (body[counter].get_octet() == '\n')) { - break; - } - counter += 1; - } // End of 'while' statement - loggers::get_instance().log("http_codec::decode_body: Chunked(0): prev = %d, counter=%d / %d", prev, counter, body.lengthof()); - if (counter < body.lengthof()) { - int idx = counter - prev; - OCTETSTRING trunk(idx, static_cast(body)); - loggers::get_instance().log_msg("http_codec::decode_body: trunk: ", trunk); - std::string str((const char *)static_cast(trunk), idx); - loggers::get_instance().log("http_codec::decode_body: str: '%s'", str.c_str()); - int len = std::stoi(str, nullptr, 16); // converter::get_instance().string_to_int(str); - loggers::get_instance().log("http_codec::decode_body: Chunk len: %d", len); - while (counter < body.lengthof() && ((body[counter].get_octet() == '\r') || (body[counter].get_octet() == '\n'))) { // Skip additional \n - counter += 1; - } // End of 'while' statement - if (counter < body.lengthof()) { - loggers::get_instance().log("http_codec::decode_body: Chunked (1): prev = %d, counter=%d / %d", prev, counter, body.lengthof()); - os += OCTETSTRING(len, counter + static_cast(body)); - loggers::get_instance().log_msg("http_codec::decode_body: os=", os); - counter += len; - loggers::get_instance().log("http_codec::decode_body: Chunked: %02x %02x %02x", body[counter].get_octet(), body[counter + 1].get_octet(), - body[counter + 2].get_octet()); - loggers::get_instance().log("http_codec::decode_body: Chunked (2): prev = %d, counter=%d / %d", prev, counter, body.lengthof()); - while (counter < body.lengthof() && ((body[counter].get_octet() == '\r') || (body[counter].get_octet() == '\n'))) { // Skip additional \n - counter += 1; - } // End of 'while' statement - prev = counter; - loggers::get_instance().log("http_codec::decode_body: Chunked (3): prev = %d, counter=%d / %d", prev, counter, body.lengthof()); - } - } - } while (counter < body.lengthof()); // Process next chunk if any - body = os; - loggers::get_instance().log_msg("http_codec::decode_body: Finalised body=", body); - } - // Check if HTTP message body contains binary characters - for (int i = 0; i < body.lengthof(); i++) { - unsigned char c = body[i].get_octet(); - if (!std::isprint(c) && !std::isspace(c) && !std::ispunct(c)) { - loggers::get_instance().log("http_codec::decode_body: Byte #%d is not printable: 0x%02x", i, body[i].get_octet()); - _dc.is_binary = 0x01; - break; - } - } // End of 'for' statement - loggers::get_instance().log("http_codec::decode_body: Binary mode: %x", _dc.is_binary); - LibHttp__MessageBodyTypes::HttpMessageBody v; - if (_dc.is_binary == 0x01) { - LibHttp__BinaryMessageBodyTypes::BinaryBody binary_body; - decode_body_binary(body, binary_body, p_content_type); - message_body.binary__body() = binary_body; - } else { - // Convert into string - params p; - p["decode_str"] = std::string(static_cast(body), body.lengthof() + static_cast(body)); - loggers::get_instance().log("http_codec::decode_body: decode_str: %s", p["decode_str"].c_str()); - // Try to identify xml - if (p["decode_str"].find("") != std::string::npos) { // Try to identify HTML - loggers::get_instance().log("http_codec::decode_body: Find html message"); - LibHttp__MessageBodyTypes::HtmlBody html_body; - decode_body_html(body, html_body, p_content_type, &p); - message_body.html__body() = html_body; - } else if (p_content_type.find("json") != std::string::npos) { // Try to identify JSON - loggers::get_instance().log("http_codec::decode_body: Find json message"); - LibHttp__JsonMessageBodyTypes::JsonBody json_body; - decode_body_json(body, json_body, p_content_type, &p); - message_body.json__body() = json_body; - } else { - loggers::get_instance().log("http_codec::decode_body: Use textBody as default"); - LibHttp__MessageBodyTypes::TextBody text_body; - message_body.text__body() = CHARSTRING(body.lengthof(), (char *)static_cast(body)); - } - } - - return 0; -} - -int http_codec::get_line(TTCN_Buffer &buffer, CHARSTRING &to, const bool concatenate_header_lines) { - unsigned int i = 0; - const unsigned char *cc_to = buffer.get_read_data(); - - // Sanity checks - if (buffer.get_read_len() == 0) { - return -1; - } - - while (true) { - // Skip spaces, and empty lines - for (; i < buffer.get_read_len() && cc_to[i] != '\0' && cc_to[i] != '\r' && cc_to[i] != '\n'; i++) - ; - if (i >= buffer.get_read_len()) { // No more characters to process - to = CHARSTRING(""); - return -1; - } else if (cc_to[i] == '\n') { // New line found, we don't care is '\r' is missing - if ((i > 0) && ((i + 1) < buffer.get_read_len()) && concatenate_header_lines && ((cc_to[i + 1] == ' ') || (cc_to[i + 1] == '\t'))) { - i += 1; // Skip it - } else { - to = CHARSTRING(i, (const char *)cc_to); - buffer.set_pos(buffer.get_pos() + i + 1); - return i == 0 ? 1 : 0; - } - } else { - if ((i + 1) < buffer.get_read_len() && cc_to[i + 1] != '\n') { - return -1; - } else if (i > 0 && (i + 2) < buffer.get_read_len() && concatenate_header_lines && (cc_to[i + 2] == ' ' || cc_to[i + 2] == '\t')) { - i += 2; - } else { - to = CHARSTRING(i, (const char *)cc_to); - buffer.set_pos(buffer.get_pos() + i + 2); - return i == 0 ? 1 : 0; - } - } - } // End of 'while' statement -} - -void http_codec::set_payload_codecs(const std::string &p_codecs) { - loggers::get_instance().log(">>> http_codec::set_payload_codecs: %s", p_codecs.c_str()); - - // Sanity check - if (p_codecs.length() == 0) { - return; - } - - // Extract codecs - try { - std::regex rgx("(\\w+):(\\w+)(;(\\w+):(\\w+))*"); - std::sregex_iterator begin(p_codecs.cbegin(), p_codecs.cend(), rgx); - std::sregex_iterator end = std::sregex_iterator(); - // E.g. 9 - xml - :held_codec - held_codec - ;html:html_codec - html:html_codec - html - :html_codec - html_codec - for (std::sregex_iterator it = begin; it != end; ++it) { - std::smatch m = *it; - loggers::get_instance().log("http_codec::set_payload_codecs: %d - %s - %s - %s - %s - %s - %s - %s - %s", m.size(), m[1].str().c_str(), - m[2].str().c_str(), m[3].str().c_str(), m[4].str().c_str(), m[5].str().c_str(), m[6].str().c_str(), m[7].str().c_str(), - m[8].str().c_str()); - for (unsigned int j = 1; j < m.size() - 1; j += 3) { // Exclude m[0] - loggers::get_instance().log("http_codec::set_payload_codecs: insert (%s, %s), j = %d", m[j].str().c_str(), m[j + 1].str().c_str(), j); - if (m[j].str().empty()) { - break; - } - std::string key(m[j].str()); - loggers::get_instance().log("http_codec::set_payload_codecs: Add codec %s", key.c_str()); - _codecs.insert( - std::make_pair(key, std::unique_ptr>(codec_stack_builder::get_instance()->get_codec(m[j + 1].str().c_str())))); - } // End of 'for' statement - } // End of 'for' statement - loggers::get_instance().log("http_codec::set_payload_codecs: _codecs length=%d - %p", _codecs.size(), this); - } catch (const std::logic_error &e) { - loggers::get_instance().warning("http_codec::set_payload_codecs: std::logic_error: %s", e.what()); - _codecs.clear(); - } -} - -bool http_codec::decode_body_html(const OCTETSTRING &p_data, CHARSTRING &p_html_body, const std::string &p_content_type, params* p_params) { - p_html_body = CHARSTRING(p_data.lengthof(), (char*)static_cast(p_data)); - return true; -} +#include +#include +#include + +#include "codec_stack_builder.hh" + +#include "http_codec.hh" + +#include "loggers.hh" + +#include "LibHttp_TypesAndValues.hh" +#include "LibHttp_MessageBodyTypes.hh" +#include "LibHttp_XmlMessageBodyTypes.hh" +#include "LibHttp_JsonMessageBodyTypes.hh" + +int http_codec::encode(const LibHttp__TypesAndValues::HttpMessage &msg, OCTETSTRING &data) { + loggers::get_instance().log_msg(">>> http_codec::encode: ", (const Base_Type &)msg); + loggers::get_instance().log(">>> http_codec::encode: %p", this); + + TTCN_EncDec::clear_error(); + TTCN_Buffer encoding_buffer; + + _ec.reset(); + + int result; + if (msg.ischosen(LibHttp__TypesAndValues::HttpMessage::ALT_request)) { + result = encode_request(msg.request(), encoding_buffer); + } else if (msg.ischosen(LibHttp__TypesAndValues::HttpMessage::ALT_response)) { + result = encode_response(msg.response(), encoding_buffer); + } else { + loggers::get_instance().warning("http_codec::encode: Unbound HttpMessage"); + return -1; + } + + data = OCTETSTRING(encoding_buffer.get_len(), encoding_buffer.get_data()); + + loggers::get_instance().log_msg("<<< http_codec::encode: data=", data); + return result; +} + +int http_codec::decode(const OCTETSTRING &data, LibHttp__TypesAndValues::HttpMessage &msg, params *params) { + loggers::get_instance().log_msg(">>> http_codec::decode: data=", data); + + // Sanity checks + if ((data[0].get_octet() & 0x80) == 0x80) { + loggers::get_instance().warning("http_codec::decode: Unicode format not supported"); + return -1; + } + + TTCN_EncDec::clear_error(); + TTCN_Buffer decoding_buffer(data); + loggers::get_instance().log_to_hexa("http_codec::decode: decoding_buffer=", decoding_buffer); + + _dc.reset(); + + _params = params; + + // Get the first line (e.g. HTTP/1.1 302 Found or POST / HTTP/1.1) + CHARSTRING message_id; + if (get_line(decoding_buffer, message_id) == -1) { + loggers::get_instance().warning("http_codec::decode: get_line failed, errno: %d", errno); + return -1; + } + loggers::get_instance().log_msg("http_codec::decode: message_id: ", message_id); + // Extract parameters + try { + std::string str(static_cast(message_id)); + std::regex rgx("\\s*(\\w+)/"); + std::sregex_iterator begin(str.cbegin(), str.cend(), rgx); + std::smatch m = *begin; + loggers::get_instance().log("http_codec::decode: %d - %s", m.size(), m[0].str().c_str()); + if (m[0].str().compare("HTTP/") == 0) { // HTTP response + LibHttp__TypesAndValues::Response response; + std::regex rgx("\\s*HTTP/(\\d+)\\.(\\d+)\\s+(\\d+)\\s+([\\w\\s\\t\\v\\f]+)*"); + std::sregex_iterator begin(str.cbegin(), str.cend(), rgx); + std::smatch m = *begin; + loggers::get_instance().log("http_codec::decode: Process response: %d", m.size()); + if (m.size() != 5) { + loggers::get_instance().warning("http_codec::decode: Unsupported tag"); + return -1; + } + response.version__major() = std::stoi(m[1].str().c_str()); + response.version__minor() = std::stoi(m[2].str().c_str()); + response.statuscode() = std::stoi(m[3].str().c_str()); + response.statustext() = CHARSTRING(m[4].str().c_str()); + LibHttp__TypesAndValues::Headers headers; + std::string content_type; + decode_headers(decoding_buffer, headers, content_type); + response.header() = headers; + loggers::get_instance().log_to_hexa("Before decoding Body: ", decoding_buffer); + LibHttp__MessageBodyTypes::HttpMessageBody body; + if (decode_body(decoding_buffer, body, content_type) == -1) { + response.body().set_to_omit(); + } else { + response.body() = OPTIONAL(body); + } + // Add lower layers parameters + loggers::get_instance().log("http_codec::decode: Add lower layers parameters"); + params->log(); + params::const_iterator it = params->find(params::use_ssl); + if (it != params->cend()) { + loggers::get_instance().log("http_codec::receive_data: tls=%s", it->second.c_str()); + response.tls() = (it->second.compare("1") == 0) ? true : false; + } else { + response.tls().set_to_omit(); + } + it = params->find(params::mutual_auth); + if (it != params->cend()) { + loggers::get_instance().log("http_codec::receive_data: mutual_tls=%s", it->second.c_str()); + response.mutual__tls() = (it->second.compare("1") == 0) ? true : false; + } else { + response.mutual__tls().set_to_omit(); + } + msg.response() = response; + } else { // HTTP request + LibHttp__TypesAndValues::Request request; + std::regex rgx("\\s*(\\w+)\\s+(.+)\\s+HTTP/(\\d)\\.(\\d)"); + std::sregex_iterator begin(str.cbegin(), str.cend(), rgx); + std::smatch m = *begin; + if (m.size() != 5) { + loggers::get_instance().error("http_codec::decode: Unsupported tag"); + return -1; + } + request.method() = CHARSTRING(m[1].str().c_str()); + request.uri() = CHARSTRING(m[2].str().c_str()); + request.version__major() = std::stoi(m[3].str().c_str()); + request.version__minor() = std::stoi(m[4].str().c_str()); + LibHttp__TypesAndValues::Headers headers; + std::string content_type; + decode_headers(decoding_buffer, headers, content_type); + request.header() = headers; + OPTIONAL body; + body.set_to_omit(); + if (decode_body(decoding_buffer, body, content_type) == -1) { + request.body().set_to_omit(); + } else { + request.body() = body; + } + msg.request() = request; + } + + loggers::get_instance().log_msg("<<< http_codec::decode: ", (const Base_Type &)msg); + return 0; + } catch (const std::logic_error &e) { + return -1; + } +} + +int http_codec::encode_request(const LibHttp__TypesAndValues::Request &p_request, TTCN_Buffer &p_encoding_buffer) { + loggers::get_instance().log_msg(">>> http_codec::encode_request: ", (const Base_Type &)p_request); + + // Encode generic part + p_encoding_buffer.put_cs(p_request.method()); + p_encoding_buffer.put_c(' '); + p_encoding_buffer.put_cs(p_request.uri()); + p_encoding_buffer.put_cs(" HTTP/"); + p_encoding_buffer.put_cs(int2str(p_request.version__major())); + p_encoding_buffer.put_c('.'); + p_encoding_buffer.put_cs(int2str(p_request.version__minor())); + p_encoding_buffer.put_cs("\r\n"); + + // Encode headers excepeted the Content-Length + const LibHttp__TypesAndValues::Headers &headers = p_request.header(); + std::string content_type; + for (int i = 0; i < headers.size_of(); i++) { + const LibHttp__TypesAndValues::Header &header = headers[i]; + loggers::get_instance().log_msg("http_codec::encode_request: Processing header ", header.header__name()); + if (std::string(static_cast(header.header__name())).compare("Content-Length") == 0) { // Skip it, processed later + loggers::get_instance().log("http_codec::encode_request: Skip it"); + continue; + } else { + p_encoding_buffer.put_cs(header.header__name()); + p_encoding_buffer.put_cs(": "); + const OPTIONAL &o = header.header__value(); + if (o.ispresent()) { + const LibHttp__TypesAndValues::charstring__list &v = dynamic_cast &>(o); + if (v.size_of() > 0) { + loggers::get_instance().log_msg("http_codec::encode_request: Processing value ", v[0]); + if (std::string(static_cast(header.header__name())).compare("Content-Type") == 0) { // Store it for HTTP body payload encoding + loggers::get_instance().log("http_codec::encode_request: Storing Content-Type"); + int j = 0; + while (j < v.size_of()) { + content_type += v[j++]; + } // End of 'while' statement + } + p_encoding_buffer.put_cs(v[0]); + int j = 1; + while (j < v.size_of()) { + p_encoding_buffer.put_cs(", "); + loggers::get_instance().log_msg("http_codec::encode_request: Processing value ", v[j]); + p_encoding_buffer.put_cs(v[j++]); + } // End of 'while' statement + } + } // else, do not include it + } + p_encoding_buffer.put_cs("\r\n"); + } // End of 'for' statement + + // Encode message body + const OPTIONAL &v = p_request.body(); + OCTETSTRING os; + if (v.ispresent()) { + const LibHttp__MessageBodyTypes::HttpMessageBody &body = static_cast(*v.get_opt_value()); + loggers::get_instance().log_msg("http_codec::encode_request: body: ", body); + if (encode_body(body, os, content_type) == -1) { + loggers::get_instance().warning("http_codec::encode_request: Failed to encode HTTP body"); + _ec.length = 0; + _ec.is_content_length_present = 0x00; + } else { + _ec.length = os.lengthof(); + _ec.is_content_length_present = 0x01; + } + loggers::get_instance().log("http_codec::encode_request: length=%d", _ec.length); + } else { + loggers::get_instance().log("http_codec::encode_request: HTTP body field not present"); + _ec.length = 0; + _ec.is_content_length_present = 0x00; + } + + // Encode Content-Length header + p_encoding_buffer.put_cs("Content-Length: "); + if (_ec.length != 0) { + loggers::get_instance().log("http_codec::encode_request: Content-Length: %s", + static_cast(int2str(_ec.length + 2 /*Stand for the last CRLF*/))); + p_encoding_buffer.put_cs(static_cast(int2str(_ec.length))); + _ec.is_content_length_present = 0x01; + } else { + p_encoding_buffer.put_cs("0"); + _ec.is_content_length_present = 0x00; + } + loggers::get_instance().log("http_codec::encode_request: Content-Length: %d - %x", _ec.length, _ec.is_content_length_present); + p_encoding_buffer.put_cs("\r\n"); + + // Add message body + p_encoding_buffer.put_cs("\r\n"); + if (_ec.is_content_length_present == 0x01) { + loggers::get_instance().log_msg("http_codec::encode_request: Add body ", os); + p_encoding_buffer.put_os(os); + // p_encoding_buffer.put_cs("\r\n"); + } + + loggers::get_instance().log_to_hexa("<<< http_codec::encode_request: ", p_encoding_buffer); + return 0; +} + +int http_codec::encode_response(const LibHttp__TypesAndValues::Response &p_response, TTCN_Buffer &p_encoding_buffer) { + loggers::get_instance().log_msg(">>> http_codec::encode_response: ", (const Base_Type &)p_response); + + // Encode generic part + p_encoding_buffer.put_cs("HTTP/"); + p_encoding_buffer.put_cs(int2str(p_response.version__major())); + p_encoding_buffer.put_c('.'); + p_encoding_buffer.put_cs(int2str(p_response.version__minor())); + p_encoding_buffer.put_cs(" "); + p_encoding_buffer.put_cs(int2str(p_response.statuscode())); + p_encoding_buffer.put_cs(" "); + if (p_response.statustext().lengthof() != 0) { + p_encoding_buffer.put_cs(p_response.statustext()); + } + p_encoding_buffer.put_cs("\r\n"); + + // Encode headers excepeted the Content-Length + const LibHttp__TypesAndValues::Headers &headers = p_response.header(); + std::string content_type; + for (int i = 0; i < headers.size_of(); i++) { + const LibHttp__TypesAndValues::Header &header = headers[i]; + loggers::get_instance().log_msg("http_codec::encode_response: Processing header ", header.header__name()); + if (std::string(static_cast(header.header__name())).compare("Content-Length") == 0) { + continue; + } else { + p_encoding_buffer.put_cs(header.header__name()); + p_encoding_buffer.put_cs(": "); + const OPTIONAL &o = header.header__value(); + if (o.ispresent()) { + const LibHttp__TypesAndValues::charstring__list &v = dynamic_cast &>(o); + if (v.size_of() > 0) { + loggers::get_instance().log_msg("http_codec::encode_response: Processing value ", v[0]); + if (std::string(static_cast(header.header__name())).compare("Content-Type") == 0) { // Store it for HTTP body payload encoding + loggers::get_instance().log("http_codec::encode_response: Storing Content-Type"); + int j = 0; + while (j < v.size_of()) { + content_type += v[j++]; + } // End of 'while' statement + } + p_encoding_buffer.put_cs(v[0]); + int j = 1; + while (j < v.size_of()) { + p_encoding_buffer.put_cs(", "); + loggers::get_instance().log_msg("http_codec::encode_response: Processing value ", v[j]); + p_encoding_buffer.put_cs(v[j++]); + j += 1; + } // End of 'while' statement + } + } // else, do not include it + } + p_encoding_buffer.put_cs("\r\n"); + } // End of 'for' statement + + // Encode message body + const OPTIONAL &v = p_response.body(); + OCTETSTRING os; + if (v.ispresent()) { + const LibHttp__MessageBodyTypes::HttpMessageBody &body = static_cast(*v.get_opt_value()); + loggers::get_instance().log_msg("http_codec::encode_response: body: ", body); + if (encode_body(body, os, content_type) == -1) { + _ec.length = 0; + _ec.is_content_length_present = 0x00; + } else { + _ec.length = os.lengthof(); + _ec.is_content_length_present = 0x01; + } + loggers::get_instance().log("http_codec::encode_response: length=%d", _ec.length); + } else { + loggers::get_instance().log("http_codec::encode_response: HTTP body field not present"); + _ec.length = 0; + _ec.is_content_length_present = 0x00; + } + + // Encode Content-Length header + p_encoding_buffer.put_cs("Content-Length: "); + if (_ec.length != 0) { + loggers::get_instance().log("http_codec::encode_request: Content-Length: %s", + static_cast(int2str(_ec.length + 2 /*Stand for the last CRLF*/))); + p_encoding_buffer.put_cs(static_cast(int2str(_ec.length))); + _ec.is_content_length_present = 0x01; + } else { + p_encoding_buffer.put_cs("0"); + _ec.is_content_length_present = 0x00; + } + loggers::get_instance().log("http_codec::encode_request: Content-Length: %d - %x", _ec.length, _ec.is_content_length_present); + p_encoding_buffer.put_cs("\r\n"); + + // Add message body + p_encoding_buffer.put_cs("\r\n"); + if (_ec.is_content_length_present == 0x01) { + loggers::get_instance().log_msg("http_codec::encode_request: Add body ", os); + p_encoding_buffer.put_os(os); + // p_encoding_buffer.put_cs("\r\n"); + } + + loggers::get_instance().log_to_hexa("<<< http_codec::encode_response: ", p_encoding_buffer); + return 0; +} + +int http_codec::decode_headers(TTCN_Buffer &decoding_buffer, LibHttp__TypesAndValues::Headers &headers, std::string &p_content_type) { + loggers::get_instance().log(">>> http_codec::decode_headers"); + loggers::get_instance().log_to_hexa("http_codec::decode_headers: ", decoding_buffer); + + CHARSTRING cstr; + int i = 0; + while (true) { + switch (get_line(decoding_buffer, cstr, true)) { + case 0: { + loggers::get_instance().log_msg("http_codec::decode_headers: ", cstr); + LibHttp__TypesAndValues::Header header; + if (decode_header(cstr, header) == -1) { + loggers::get_instance().warning("http_codec::decode_headers: Failed to decode header %s", static_cast(cstr)); + return -1; + } + headers[i++] = header; + if (std::string(static_cast(header.header__name())).compare("Content-Type") == 0) { + if (header.header__value().is_present() != 0) { + const PreGenRecordOf::PREGEN__RECORD__OF__CHARSTRING &l = + static_cast(*header.header__value().get_opt_value()); + p_content_type = static_cast(l[0]); + } else { + p_content_type = ""; + } + } + } break; + case 1: + if (headers.is_bound()) { + loggers::get_instance().log_msg("<<< http_codec::decode_headers: ", headers); + return 0; + } else { + loggers::get_instance().warning("http_codec::decode_headers: Failed to decode headers"); + return -1; + } + case -1: + loggers::get_instance().warning("http_codec::decode_headers: Failed to decode headers"); + return -1; + } // End of 'switch' statement + } // End of 'while' statement +} + +int http_codec::decode_header(CHARSTRING &header_line, LibHttp__TypesAndValues::Header &header) { + loggers::get_instance().log_msg(">>> http_codec::decode_header", header_line); + + try { + std::string str(static_cast(header_line)); + std::regex rgx("([0-9a-zA-Z-]+)\\:\\s+(.+)(,(.+))*"); + std::sregex_iterator begin(str.cbegin(), str.cend(), rgx); + std::smatch m = *begin; + if (m.size() < 5) { + loggers::get_instance().warning("http_codec::decode_header: Failed to decode header %s", str.c_str()); + return -1; + } + loggers::get_instance().log("http_codec::decode_header: %d", m.size()); + header.header__name() = CHARSTRING(m[1].str().c_str()); + LibHttp__TypesAndValues::charstring__list v; + for (unsigned int j = 0; j < m.size(); j++) { + if (m[j + 2].str().length() == 0) { + break; + } + v[j] = CHARSTRING(m[j + 2].str().c_str()); + } // End of 'for' statement + header.header__value() = OPTIONAL(v); + + if (m[1].str().compare("Content-Length") == 0) { + // Save the the body length + loggers::get_instance().log("http_codec::decode_header: decoded Content-Length %s", m[2].str().c_str()); + _dc.length = std::stoi(m[2].str()); + } else if (m[1].str().compare("Transfer-Encoding") == 0) { + if (m[2].str().find("chunked") != std::string::npos) { + _dc.chunked = true; + loggers::get_instance().log("http_codec::decode_header: decoded Transfer-Encoding %x", _dc.chunked); + } + } + + return 0; + } catch (const std::logic_error &e) { + return -1; + } +} + +int http_codec::encode_body(const LibHttp__MessageBodyTypes::HttpMessageBody &p_message_body, OCTETSTRING &p_encoding_buffer, + const std::string &p_content_type) { + loggers::get_instance().log_msg(">>> http_codec::encode_body: ", (const Base_Type &)p_message_body); + + // Sanity check + if (p_content_type.empty()) { + loggers::get_instance().warning("http_codec::encode_body: Failed to select a codec for HTTP body payload"); + return -1; + } + + if (p_message_body.ischosen(LibHttp__MessageBodyTypes::HttpMessageBody::ALT_binary__body)) { + const LibHttp__BinaryMessageBodyTypes::BinaryBody &binary_body = p_message_body.binary__body(); + if (binary_body.ischosen(LibHttp__BinaryMessageBodyTypes::BinaryBody::ALT_raw)) { + p_encoding_buffer = OCTETSTRING(binary_body.raw().lengthof(), (unsigned char *)static_cast(binary_body.raw())); + } else { + encode_body_binary(binary_body, p_encoding_buffer, p_content_type); + } + } else if (p_message_body.ischosen(LibHttp__MessageBodyTypes::HttpMessageBody::ALT_json__body)) { + const LibHttp__JsonMessageBodyTypes::JsonBody& json_body = p_message_body.json__body(); + if (json_body.ischosen(LibHttp__JsonMessageBodyTypes::JsonBody::ALT_raw)) { + p_encoding_buffer = unichar2oct(json_body.raw()); + } else { + encode_body_json(json_body, p_encoding_buffer, p_content_type); + } + } else if (p_message_body.ischosen(LibHttp__MessageBodyTypes::HttpMessageBody::ALT_xml__body)) { + const LibHttp__XmlMessageBodyTypes::XmlBody &xml_body = p_message_body.xml__body(); + if (xml_body.ischosen(LibHttp__XmlMessageBodyTypes::XmlBody::ALT_raw)) { + p_encoding_buffer = OCTETSTRING(xml_body.raw().lengthof(), (unsigned char *)static_cast(xml_body.raw())); + } else { + encode_body_xml(xml_body, p_encoding_buffer, p_content_type); + } + } else if (p_message_body.ischosen(LibHttp__MessageBodyTypes::HttpMessageBody::ALT_html__body)) { + p_encoding_buffer = OCTETSTRING(p_message_body.html__body().lengthof(), (unsigned char *)static_cast(p_message_body.html__body())); + } else if (p_message_body.ischosen(LibHttp__MessageBodyTypes::HttpMessageBody::ALT_text__body)) { + p_encoding_buffer = OCTETSTRING(p_message_body.text__body().lengthof(), (unsigned char *)static_cast(p_message_body.text__body())); + } else { + loggers::get_instance().warning("http_codec::encode_body: Failed to encode HTTP message body"); + return -1; + } + loggers::get_instance().log_msg("http_codec::encode_body: HTTP message ", p_encoding_buffer); + _ec.length = p_encoding_buffer.lengthof(); + loggers::get_instance().log("http_codec::encode_body: HTTP message length: %d", _ec.length); + + return 0; +} + +int http_codec::decode_body(TTCN_Buffer &decoding_buffer, LibHttp__MessageBodyTypes::HttpMessageBody &message_body, const std::string &p_content_type) { + loggers::get_instance().log(">>> http_codec::decode_body"); + loggers::get_instance().log_to_hexa("http_codec::decode_body", decoding_buffer); + loggers::get_instance().log("http_codec::decode_body: # of codecs=%d - %p", _codecs.size(), this); + loggers::get_instance().log("http_codec::decode_body: Content-Type=%s", p_content_type.c_str()); + + // Sanity checks + if (decoding_buffer.get_len() - decoding_buffer.get_pos() <= 0) { + return -1; + } + /* TODO Uncomment if (p_content_type.empty()) { + loggers::get_instance().warning("http_codec::encode_body: Failed to select a codec for HTTP body payload"); + return -1; + }*/ + + OCTETSTRING s(decoding_buffer.get_len() - decoding_buffer.get_pos(), decoding_buffer.get_data() + decoding_buffer.get_pos()); + loggers::get_instance().log_msg("http_codec::decode_body: raw body=", s); + + // Align the payload length with the specified Content-Lenght value + loggers::get_instance().log("http_codec::decode_body: _dc.length=%d - body length=%d", _dc.length, s.lengthof()); + OCTETSTRING body; + if (_dc.length != 0) { + const unsigned char *p = static_cast(s); + if ((unsigned int)s.lengthof() <= _dc.length) { + body = OCTETSTRING(s.lengthof(), p); + } else { + body = OCTETSTRING(_dc.length, p); + } + } else { + loggers::get_instance().warning("http_codec::decode_body: No Conten-Length header, process all remaining bytes"); + body = s; + } + loggers::get_instance().log_msg("http_codec::decode_body: Aligned body=", body); + loggers::get_instance().log("http_codec::decode_body: body length=%d", body.lengthof()); + /* TODO To be removed + // Remove CRLF if any + int counter = 0; + if ((body[body.lengthof() - 1].get_octet() == 0x0d) || (body[body.lengthof() - 1].get_octet() == 0x0a)) { + counter += 1; + if ((body[body.lengthof() - 2].get_octet() == 0x0d) || (body[body.lengthof() - 2].get_octet() == 0x0a)) { + counter += 1; + } + } + loggers::get_instance().log("http_codec::decode_body: counter=%d", counter); + body = OCTETSTRING(body.lengthof() - counter, static_cast(body)); + */ + if (_dc.chunked) { + int counter = 0; + int prev = 0; + OCTETSTRING os(0, nullptr); + do { + while (counter < body.lengthof()) { // Extract the size of the chunk \r[\n] + if ((body[counter].get_octet() == '\r') || (body[counter].get_octet() == '\n')) { + break; + } + counter += 1; + } // End of 'while' statement + loggers::get_instance().log("http_codec::decode_body: Chunked(0): prev = %d, counter=%d / %d", prev, counter, body.lengthof()); + if (counter < body.lengthof()) { + int idx = counter - prev; + OCTETSTRING trunk(idx, static_cast(body)); + loggers::get_instance().log_msg("http_codec::decode_body: trunk: ", trunk); + std::string str((const char *)static_cast(trunk), idx); + loggers::get_instance().log("http_codec::decode_body: str: '%s'", str.c_str()); + int len = std::stoi(str, nullptr, 16); // converter::get_instance().string_to_int(str); + loggers::get_instance().log("http_codec::decode_body: Chunk len: %d", len); + while (counter < body.lengthof() && ((body[counter].get_octet() == '\r') || (body[counter].get_octet() == '\n'))) { // Skip additional \n + counter += 1; + } // End of 'while' statement + if (counter < body.lengthof()) { + loggers::get_instance().log("http_codec::decode_body: Chunked (1): prev = %d, counter=%d / %d", prev, counter, body.lengthof()); + os += OCTETSTRING(len, counter + static_cast(body)); + loggers::get_instance().log_msg("http_codec::decode_body: os=", os); + counter += len; + loggers::get_instance().log("http_codec::decode_body: Chunked: %02x %02x %02x", body[counter].get_octet(), body[counter + 1].get_octet(), + body[counter + 2].get_octet()); + loggers::get_instance().log("http_codec::decode_body: Chunked (2): prev = %d, counter=%d / %d", prev, counter, body.lengthof()); + while (counter < body.lengthof() && ((body[counter].get_octet() == '\r') || (body[counter].get_octet() == '\n'))) { // Skip additional \n + counter += 1; + } // End of 'while' statement + prev = counter; + loggers::get_instance().log("http_codec::decode_body: Chunked (3): prev = %d, counter=%d / %d", prev, counter, body.lengthof()); + } + } + } while (counter < body.lengthof()); // Process next chunk if any + body = os; + loggers::get_instance().log_msg("http_codec::decode_body: Finalised body=", body); + } + // Check if HTTP message body contains binary characters + for (int i = 0; i < body.lengthof(); i++) { + unsigned char c = body[i].get_octet(); + if (!std::isprint(c) && !std::isspace(c) && !std::ispunct(c)) { + loggers::get_instance().log("http_codec::decode_body: Byte #%d is not printable: 0x%02x", i, body[i].get_octet()); + _dc.is_binary = 0x01; + break; + } + } // End of 'for' statement + loggers::get_instance().log("http_codec::decode_body: Binary mode: %x", _dc.is_binary); + LibHttp__MessageBodyTypes::HttpMessageBody v; + if (_dc.is_binary == 0x01) { + LibHttp__BinaryMessageBodyTypes::BinaryBody binary_body; + decode_body_binary(body, binary_body, p_content_type); + message_body.binary__body() = binary_body; + } else { + // Convert into string + params p; + p["decode_str"] = std::string(static_cast(body), body.lengthof() + static_cast(body)); + loggers::get_instance().log("http_codec::decode_body: decode_str: %s", p["decode_str"].c_str()); + // Try to identify xml + if (p["decode_str"].find("") != std::string::npos) { // Try to identify HTML + loggers::get_instance().log("http_codec::decode_body: Find html message"); + LibHttp__MessageBodyTypes::HtmlBody html_body; + decode_body_html(body, html_body, p_content_type, &p); + message_body.html__body() = html_body; + } else if (p_content_type.find("json") != std::string::npos) { // Try to identify JSON + loggers::get_instance().log("http_codec::decode_body: Find json message"); + LibHttp__JsonMessageBodyTypes::JsonBody json_body; + decode_body_json(body, json_body, p_content_type, &p); + message_body.json__body() = json_body; + } else { + loggers::get_instance().log("http_codec::decode_body: Use textBody as default"); + LibHttp__MessageBodyTypes::TextBody text_body; + message_body.text__body() = CHARSTRING(body.lengthof(), (char *)static_cast(body)); + } + } + + return 0; +} + +int http_codec::get_line(TTCN_Buffer &buffer, CHARSTRING &to, const bool concatenate_header_lines) { + unsigned int i = 0; + const unsigned char *cc_to = buffer.get_read_data(); + + // Sanity checks + if (buffer.get_read_len() == 0) { + return -1; + } + + while (true) { + // Skip spaces, and empty lines + for (; i < buffer.get_read_len() && cc_to[i] != '\0' && cc_to[i] != '\r' && cc_to[i] != '\n'; i++) + ; + if (i >= buffer.get_read_len()) { // No more characters to process + to = CHARSTRING(""); + return -1; + } else if (cc_to[i] == '\n') { // New line found, we don't care is '\r' is missing + if ((i > 0) && ((i + 1) < buffer.get_read_len()) && concatenate_header_lines && ((cc_to[i + 1] == ' ') || (cc_to[i + 1] == '\t'))) { + i += 1; // Skip it + } else { + to = CHARSTRING(i, (const char *)cc_to); + buffer.set_pos(buffer.get_pos() + i + 1); + return i == 0 ? 1 : 0; + } + } else { + if ((i + 1) < buffer.get_read_len() && cc_to[i + 1] != '\n') { + return -1; + } else if (i > 0 && (i + 2) < buffer.get_read_len() && concatenate_header_lines && (cc_to[i + 2] == ' ' || cc_to[i + 2] == '\t')) { + i += 2; + } else { + to = CHARSTRING(i, (const char *)cc_to); + buffer.set_pos(buffer.get_pos() + i + 2); + return i == 0 ? 1 : 0; + } + } + } // End of 'while' statement +} + +void http_codec::set_payload_codecs(const std::string &p_codecs) { + loggers::get_instance().log(">>> http_codec::set_payload_codecs: %s", p_codecs.c_str()); + + // Sanity check + if (p_codecs.length() == 0) { + return; + } + + // Extract codecs + try { + std::regex rgx("(\\w+):(\\w+)(;(\\w+):(\\w+))*"); + std::sregex_iterator begin(p_codecs.cbegin(), p_codecs.cend(), rgx); + std::sregex_iterator end = std::sregex_iterator(); + // E.g. 9 - xml - :held_codec - held_codec - ;html:html_codec - html:html_codec - html - :html_codec - html_codec + for (std::sregex_iterator it = begin; it != end; ++it) { + std::smatch m = *it; + loggers::get_instance().log("http_codec::set_payload_codecs: %d - %s - %s - %s - %s - %s - %s - %s - %s", m.size(), m[1].str().c_str(), + m[2].str().c_str(), m[3].str().c_str(), m[4].str().c_str(), m[5].str().c_str(), m[6].str().c_str(), m[7].str().c_str(), + m[8].str().c_str()); + for (unsigned int j = 1; j < m.size() - 1; j += 3) { // Exclude m[0] + loggers::get_instance().log("http_codec::set_payload_codecs: insert (%s, %s), j = %d", m[j].str().c_str(), m[j + 1].str().c_str(), j); + if (m[j].str().empty()) { + break; + } + std::string key(m[j].str()); + loggers::get_instance().log("http_codec::set_payload_codecs: Add codec %s", key.c_str()); + _codecs.insert( + std::make_pair(key, std::unique_ptr>(codec_stack_builder::get_instance()->get_codec(m[j + 1].str().c_str())))); + } // End of 'for' statement + } // End of 'for' statement + loggers::get_instance().log("http_codec::set_payload_codecs: _codecs length=%d - %p", _codecs.size(), this); + } catch (const std::logic_error &e) { + loggers::get_instance().warning("http_codec::set_payload_codecs: std::logic_error: %s", e.what()); + _codecs.clear(); + } +} + +bool http_codec::decode_body_html(const OCTETSTRING &p_data, CHARSTRING &p_html_body, const std::string &p_content_type, params* p_params) { + p_html_body = CHARSTRING(p_data.lengthof(), (char*)static_cast(p_data)); + return true; +} diff --git a/ccsrc/Protocols/Xml/include/xml_converters.hh b/ccsrc/Protocols/Xml/include/xml_converters.hh new file mode 100644 index 0000000..9771074 --- /dev/null +++ b/ccsrc/Protocols/Xml/include/xml_converters.hh @@ -0,0 +1,43 @@ +/*! + * \file xml_converters.hh + * \brief Header file for xml_converters functionality. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include + +#include + +/** + * \class xml_converters + * \brief This class provides XML converters such as canonicalization of XML documents before signature f encryption + */ +class xml_converters { + + static xml_converters *_instance; + +private: + xml_converters() {}; //! Can not be created manually + static int xml_node_set_contains_callback(void* user_data, xmlNodePtr node, xmlNodePtr parent); +public: + static inline xml_converters &get_instance(); + + virtual ~xml_converters() { + if (_instance != nullptr) + delete _instance; + }; + +public: + int xml_canonicalization(const std::string& p_to_canonical, std::string& p_canonicalized) const; + +}; // End of class xml_converters + +// static functions +xml_converters &xml_converters::get_instance() { return (_instance != nullptr) ? *_instance : *(_instance = new xml_converters()); } + diff --git a/ccsrc/Protocols/Xml/module.mk b/ccsrc/Protocols/Xml/module.mk new file mode 100644 index 0000000..f530e70 --- /dev/null +++ b/ccsrc/Protocols/Xml/module.mk @@ -0,0 +1,4 @@ +sources := \ + src/xml_converters.cc + +includes += ./include diff --git a/ccsrc/Protocols/Xml/src/xml_converters.cc b/ccsrc/Protocols/Xml/src/xml_converters.cc new file mode 100644 index 0000000..363cc9a --- /dev/null +++ b/ccsrc/Protocols/Xml/src/xml_converters.cc @@ -0,0 +1,62 @@ +/*! + * \file xml_converters.cc + * \brief Source file for the xml_converters functionality. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#include "xml_converters.hh" + +#include "loggers.hh" + +#include +#include + +xml_converters* xml_converters::_instance = nullptr; + +int xml_converters::xml_canonicalization(const std::string& p_to_canonical, std::string& p_canonicalized) const { + loggers::get_instance().log(">>> xml_converters::xml_canonicalization"); + + xmlDocPtr doc = xmlParseMemory(p_to_canonical.c_str(), p_to_canonical.length()); + if (doc == nullptr) { + loggers::get_instance().log("xml_converters::xml_canonicalization: Failed to read XML input"); + return -1; + } + + xmlOutputBufferPtr buffer = xmlAllocOutputBuffer(nullptr); + if (buffer == nullptr) { + loggers::get_instance().log("xml_converters::xml_canonicalization: Failed to read XML input"); + xmlFreeDoc(doc); + return -1; + } + + // Do canonicalization + loggers::get_instance().log("xml_converters::xml_canonicalization: Before"); + if (xmlC14NExecute(doc, (xmlC14NIsVisibleCallback)&xml_converters::xml_node_set_contains_callback, nullptr, XML_C14N_1_1, nullptr, 1, buffer) == -1) { + loggers::get_instance().log("xml_converters::xml_canonicalization: Failed to read XML input"); + xmlFreeDoc(doc); + xmlOutputBufferClose(buffer); + return -1; + } + loggers::get_instance().log("xml_converters::xml_canonicalization: After"); + + // Retrieve the canonicalization XML document + const char* data = (const char*)xmlOutputBufferGetContent(buffer); + size_t size = xmlOutputBufferGetSize(buffer); + p_canonicalized.assign(data, data + size); + + // Free resources + xmlOutputBufferClose(buffer); + xmlFreeDoc(doc); + + loggers::get_instance().log("<<< xml_converters::xml_canonicalization: %s", p_canonicalized.c_str()); + return 0; +} + +int xml_converters::xml_node_set_contains_callback(void* p_user_data, xmlNodePtr p_node, xmlNodePtr p_parent) { + loggers::get_instance().log("xml_converters::xml_node_set_contains_callback"); + return 1; +} diff --git a/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn b/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn index 0ee138b..e0f9967 100644 --- a/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn +++ b/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn @@ -160,6 +160,18 @@ module LibHelpers_Functions { */ external function fx_getDSecond() return UInt16; + /** + * @desc Encode into Base64 + * @return p_to_encode - The buffer to be encoded + */ + external function fx_enc_base64(in octetstring p_to_encode) return octetstring; + + /** + * @desc Decode from Base64 + * @return p_to_decode - The buffer to be decoded + */ + external function fx_dec_base64(in octetstring p_to_decode) return octetstring; + } // End of externals } // End of module LibHelpers_Functions -- GitLab From 07e483b6f5f83ea55de07fe84eaa924c7f401724 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Mon, 21 Nov 2022 16:57:33 +0100 Subject: [PATCH 08/37] Add basics for X509 support --- ccsrc/Framework/src/layer_factory.cc | 6 +- ccsrc/Framework/src/params.cc | 2 +- ccsrc/Protocols/ETH/ethernet_layer.cc | 2 +- ccsrc/Protocols/Http/http_codec.cc | 10 +- ccsrc/Protocols/Http/http_layer.cc | 2 +- ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc | 8 +- ccsrc/Protocols/Pcap/pcap_layer.cc | 12 +- ccsrc/Protocols/Pcap/pcap_linux_layer.cc | 8 +- ccsrc/Protocols/Pcap/pcap_offline_layer.cc | 6 +- ccsrc/Protocols/Tcp/tcp_layer.cc | 16 +- ccsrc/Protocols/UDP/udp_layer.cc | 10 +- ccsrc/Protocols/Xml/src/xml_converters.cc | 4 +- ccsrc/security/include/certs_cache.hh | 102 ++++++++++++ ccsrc/security/include/certs_db.hh | 49 ++++++ ccsrc/security/include/certs_db_record.hh | 62 +++++++ ccsrc/security/include/certs_loader.hh | 97 +++++++++++ ccsrc/security/include/hmac.hh | 69 ++++++++ ccsrc/security/include/security_services.hh | 40 +++++ ccsrc/security/include/sha1.hh | 66 ++++++++ ccsrc/security/include/sha256.hh | 66 ++++++++ ccsrc/security/include/sha384.hh | 60 +++++++ ccsrc/security/module.mk | 13 ++ ccsrc/security/src/certs_cache.cc | 152 ++++++++++++++++++ ccsrc/security/src/certs_db.cc | 32 ++++ ccsrc/security/src/certs_db_record.cc | 29 ++++ ccsrc/security/src/certs_loader.cc | 143 ++++++++++++++++ ccsrc/security/src/hmac.cc | 54 +++++++ ccsrc/security/src/security_externals.cc | 82 ++++++++++ ccsrc/security/src/securty_services.cc | 122 ++++++++++++++ ccsrc/security/src/sha1.cc | 39 +++++ ccsrc/security/src/sha256.cc | 39 +++++ ccsrc/security/src/sha384.cc | 47 ++++++ ttcn/LibSecurity/module.mk | 5 + .../ttcn/LibSecurity_Certificates.ttcn | 15 ++ ttcn/LibSecurity/ttcn/LibSecurity_Hash.ttcn | 21 +++ ttcn/LibSecurity/ttcn/LibSecurity_Hmac.ttcn | 2 + .../ttcn/LibSecurity_Signature.ttcn | 26 +++ 37 files changed, 1475 insertions(+), 43 deletions(-) create mode 100644 ccsrc/security/include/certs_cache.hh create mode 100644 ccsrc/security/include/certs_db.hh create mode 100644 ccsrc/security/include/certs_db_record.hh create mode 100644 ccsrc/security/include/certs_loader.hh create mode 100644 ccsrc/security/include/hmac.hh create mode 100644 ccsrc/security/include/security_services.hh create mode 100644 ccsrc/security/include/sha1.hh create mode 100644 ccsrc/security/include/sha256.hh create mode 100644 ccsrc/security/include/sha384.hh create mode 100644 ccsrc/security/module.mk create mode 100644 ccsrc/security/src/certs_cache.cc create mode 100644 ccsrc/security/src/certs_db.cc create mode 100644 ccsrc/security/src/certs_db_record.cc create mode 100644 ccsrc/security/src/certs_loader.cc create mode 100644 ccsrc/security/src/hmac.cc create mode 100644 ccsrc/security/src/security_externals.cc create mode 100644 ccsrc/security/src/securty_services.cc create mode 100644 ccsrc/security/src/sha1.cc create mode 100644 ccsrc/security/src/sha256.cc create mode 100644 ccsrc/security/src/sha384.cc create mode 100644 ttcn/LibSecurity/module.mk create mode 100644 ttcn/LibSecurity/ttcn/LibSecurity_Certificates.ttcn create mode 100644 ttcn/LibSecurity/ttcn/LibSecurity_Hash.ttcn create mode 100644 ttcn/LibSecurity/ttcn/LibSecurity_Hmac.ttcn create mode 100644 ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn diff --git a/ccsrc/Framework/src/layer_factory.cc b/ccsrc/Framework/src/layer_factory.cc index 2a10630..a28e2dc 100644 --- a/ccsrc/Framework/src/layer_factory.cc +++ b/ccsrc/Framework/src/layer_factory.cc @@ -20,7 +20,7 @@ layer_stack_builder::layer_stack_builder() {} void layer_stack_builder::_register_layer_factory(const std::string &p_type, layer_factory *p_layer_factory) { _layer_factories[p_type] = p_layer_factory; } layer *layer_stack_builder::create_layer_stack(const char *p_layer_stack_description) { - loggers::get_instance().log(">>> layer_stack_builder::create_layer_stack: %s", p_layer_stack_description); + loggers::get_instance().log(">>> layer_stack_builder::create_layer_stack: '%s'", p_layer_stack_description); layer *entry = NULL; // Initial layer (the first declared) layer *up = NULL; // Upper layer @@ -36,12 +36,12 @@ layer *layer_stack_builder::create_layer_stack(const char *p_layer_stack_descrip m[2].str().c_str(), m[3].str().c_str()); LayerFactoryMap::iterator i = _layer_factories.find(m[1].str()); if (i == _layer_factories.end()) { - loggers::get_instance().error("layer_stack_builder::create_layer_stack: %s: Unknown layer type", m[1].str().c_str()); + loggers::get_instance().error("layer_stack_builder::create_layer_stack: '%s': Unknown layer type", m[1].str().c_str()); } loggers::get_instance().log("layer_stack_builder::create_layer_stack: Create layer %s, %s", m[1].str().c_str(), m[3].str().c_str()); layer *l = i->second->create_layer(m[1].str(), m[3].str()); if (NULL == l) { - loggers::get_instance().error("layer_stack_builder::create_layer_stack: %s: Layer creation error", m[1].str().c_str()); + loggers::get_instance().error("layer_stack_builder::create_layer_stack: '%s': Layer creation error", m[1].str().c_str()); } loggers::get_instance().log("layer_stack_builder::create_layer_stack: Setup layers for %s - %p", l->to_string().c_str(), (void*)l); diff --git a/ccsrc/Framework/src/params.cc b/ccsrc/Framework/src/params.cc index 5040dbe..d58d39a 100644 --- a/ccsrc/Framework/src/params.cc +++ b/ccsrc/Framework/src/params.cc @@ -51,7 +51,7 @@ void params::convert(params &p_param, const std::string p_parameters) { if (p_parameters.length() == 0) { return; } - loggers::get_instance().log(">>> params::convert: %s", p_parameters.c_str()); + loggers::get_instance().log(">>> params::convert: '%s'", p_parameters.c_str()); // Extract parameters try { std::regex rgx("(\\w+)=(.*?)(,|$)"); diff --git a/ccsrc/Protocols/ETH/ethernet_layer.cc b/ccsrc/Protocols/ETH/ethernet_layer.cc index 33a79e1..6405a96 100644 --- a/ccsrc/Protocols/ETH/ethernet_layer.cc +++ b/ccsrc/Protocols/ETH/ethernet_layer.cc @@ -3,7 +3,7 @@ #include "loggers.hh" ethernet_layer::ethernet_layer(const std::string & p_type, const std::string & p_param) : layer(p_type), _params() { - loggers::get_instance().log(">>> ethernet_layer::ethernet_layer: %s, %s", to_string().c_str(), p_param.c_str()); + loggers::get_instance().log(">>> ethernet_layer::ethernet_layer: '%s', %s", to_string().c_str(), p_param.c_str()); // Setup parameters params::convert(_params, p_param); params::const_iterator it = _params.find("mac_src"); diff --git a/ccsrc/Protocols/Http/http_codec.cc b/ccsrc/Protocols/Http/http_codec.cc index a5818f1..f0763bb 100644 --- a/ccsrc/Protocols/Http/http_codec.cc +++ b/ccsrc/Protocols/Http/http_codec.cc @@ -220,7 +220,7 @@ int http_codec::encode_request(const LibHttp__TypesAndValues::Request &p_request // Encode Content-Length header p_encoding_buffer.put_cs("Content-Length: "); if (_ec.length != 0) { - loggers::get_instance().log("http_codec::encode_request: Content-Length: %s", + loggers::get_instance().log("http_codec::encode_request: Content-Length: '%s'", static_cast(int2str(_ec.length + 2 /*Stand for the last CRLF*/))); p_encoding_buffer.put_cs(static_cast(int2str(_ec.length))); _ec.is_content_length_present = 0x01; @@ -319,7 +319,7 @@ int http_codec::encode_response(const LibHttp__TypesAndValues::Response &p_respo // Encode Content-Length header p_encoding_buffer.put_cs("Content-Length: "); if (_ec.length != 0) { - loggers::get_instance().log("http_codec::encode_request: Content-Length: %s", + loggers::get_instance().log("http_codec::encode_request: Content-Length: '%s'", static_cast(int2str(_ec.length + 2 /*Stand for the last CRLF*/))); p_encoding_buffer.put_cs(static_cast(int2str(_ec.length))); _ec.is_content_length_present = 0x01; @@ -576,7 +576,7 @@ int http_codec::decode_body(TTCN_Buffer &decoding_buffer, LibHttp__MessageBodyTy // Convert into string params p; p["decode_str"] = std::string(static_cast(body), body.lengthof() + static_cast(body)); - loggers::get_instance().log("http_codec::decode_body: decode_str: %s", p["decode_str"].c_str()); + loggers::get_instance().log("http_codec::decode_body: decode_str: '%s'", p["decode_str"].c_str()); // Try to identify xml if (p["decode_str"].find(">> http_codec::set_payload_codecs: %s", p_codecs.c_str()); + loggers::get_instance().log(">>> http_codec::set_payload_codecs: '%s'", p_codecs.c_str()); // Sanity check if (p_codecs.length() == 0) { @@ -673,7 +673,7 @@ void http_codec::set_payload_codecs(const std::string &p_codecs) { } // End of 'for' statement loggers::get_instance().log("http_codec::set_payload_codecs: _codecs length=%d - %p", _codecs.size(), this); } catch (const std::logic_error &e) { - loggers::get_instance().warning("http_codec::set_payload_codecs: std::logic_error: %s", e.what()); + loggers::get_instance().warning("http_codec::set_payload_codecs: std::logic_error: '%s'", e.what()); _codecs.clear(); } } diff --git a/ccsrc/Protocols/Http/http_layer.cc b/ccsrc/Protocols/Http/http_layer.cc index 451c7d6..23f911c 100644 --- a/ccsrc/Protocols/Http/http_layer.cc +++ b/ccsrc/Protocols/Http/http_layer.cc @@ -13,7 +13,7 @@ using namespace std; // Required for isnan() http_layer::http_layer(const std::string &p_type, const std::string ¶m) : t_layer(p_type), _params(), _codec(nullptr), _device_mode{false} { - loggers::get_instance().log(">>> http_layer::http_layer: %s, %s", to_string().c_str(), param.c_str()); + loggers::get_instance().log(">>> http_layer::http_layer: '%s', %s", to_string().c_str(), param.c_str()); // Setup parameters params::convert(_params, param); diff --git a/ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc b/ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc index 56f9bbc..f45d70e 100644 --- a/ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc +++ b/ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc @@ -54,7 +54,7 @@ static char * _bin2hex(char *hex, size_t hlen, const char *bin, size_t blen pcap_layer::pcap_layer(const std::string &p_type, const std::string ¶m) : layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _running(FALSE), _time_key("pcap_layer::Handle_Fd_Event_Readable") { - loggers::get_instance().log(">>> pcap_layer::pcap_layer: %s, %s", p_type.c_str(), param.c_str()); + loggers::get_instance().log(">>> pcap_layer::pcap_layer: '%s', %s", p_type.c_str(), param.c_str()); params::convert(_params, param); char error_buffer[PCAP_ERRBUF_SIZE]; @@ -128,7 +128,7 @@ pcap_layer::pcap_layer(const std::string &p_type, const std::string ¶m) } // Log final PCAP filter - loggers::get_instance().user("pcap_layer::pcap_layer: Filter: %s", filter.c_str()); + loggers::get_instance().user("pcap_layer::pcap_layer: Filter: '%s'", filter.c_str()); // setup filter { @@ -147,7 +147,7 @@ pcap_layer::pcap_layer(const std::string &p_type, const std::string ¶m) // create pipe and run thread if (pipe2(_fd, O_NONBLOCK) == -1) { - loggers::get_instance().error("pcap_layer::pcap_layer: Failed to create a pipe: %s", ::strerror(errno)); + loggers::get_instance().error("pcap_layer::pcap_layer: Failed to create a pipe: '%s'", ::strerror(errno)); } // Pass the pipe handler to the polling procedure loggers::get_instance().log("pcap_layer::pcap_layer: Call handler with descriptor %d", _fd[0]); @@ -238,7 +238,7 @@ void *pcap_layer::thread() { void pcap_layer::send_data(OCTETSTRING &data, params ¶ms) { loggers::get_instance().log_msg(">>> pcap_layer::send_data: ", data); if (pcap_sendpacket(_device, static_cast(data), data.lengthof()) == -1) { - loggers::get_instance().error("pcap_layer::send_data: Failed to send packet: %s", pcap_geterr(_device)); + loggers::get_instance().error("pcap_layer::send_data: Failed to send packet: '%s'", pcap_geterr(_device)); } } diff --git a/ccsrc/Protocols/Pcap/pcap_layer.cc b/ccsrc/Protocols/Pcap/pcap_layer.cc index 8313c9f..94f7e8b 100644 --- a/ccsrc/Protocols/Pcap/pcap_layer.cc +++ b/ccsrc/Protocols/Pcap/pcap_layer.cc @@ -16,7 +16,7 @@ typedef struct timeval pcap_o_timeval; pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _pcap_h(-1), _thread(NULL), _running(FALSE), _resume(), _sent_file(NULL), _time_key("pcap_layer::Handle_Fd_Event_Readable") { bool online = false; - loggers::get_instance().log(">>> pcap_layer::pcap_layer: %s, %s", to_string().c_str(), param.c_str()); + loggers::get_instance().log(">>> pcap_layer::pcap_layer: '%s', %s", to_string().c_str(), param.c_str()); _fd[0] = -1; _fd[1] = -1; // Setup parameters params::convert(_params, param); @@ -42,7 +42,7 @@ pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : la } // else, continue // Set non-blocking flag for the polling procedure if (pcap_setnonblock(_device, 1, error_buffer) != 0) { - loggers::get_instance().error("pcap_layer::pcap_layer: Failed to set blocking mode: %s", error_buffer); + loggers::get_instance().error("pcap_layer::pcap_layer: Failed to set blocking mode: '%s'", error_buffer); } // Retrieve the device file handler _pcap_h = pcap_get_selectable_fd(_device); @@ -70,7 +70,7 @@ pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : la int i = _params["file"].find(".pcap"); if (i > 0) { std::string f(_params["file"].substr(0, i) + ext + ".pcap"); - loggers::get_instance().log("pcap_layer::pcap_layer: Save file name: %s", f.c_str()); + loggers::get_instance().log("pcap_layer::pcap_layer: Save file name: '%s'", f.c_str()); if ((_sent_file = pcap_dump_open(_device, f.c_str())) == NULL) { loggers::get_instance().warning("pcap_layer::pcap_layer: Failed to open save file %s", f.c_str()); } @@ -105,7 +105,7 @@ pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : la } // else nothing to do } // Log final PCAP filter - loggers::get_instance().user("pcap_layer::pcap_layer: Filter: %s", filter.c_str()); + loggers::get_instance().user("pcap_layer::pcap_layer: Filter: '%s'", filter.c_str()); if (!filter.empty()) { struct bpf_program f = {0}; if (pcap_compile(_device, &f, filter.c_str(), 1, PCAP_NETMASK_UNKNOWN) != 0) { @@ -123,7 +123,7 @@ pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : la } else { // Offline capture or cygwin // Create a pipe if (pipe2(_fd, O_NONBLOCK) == -1) { - loggers::get_instance().error("pcap_layer::pcap_layer: Failed to create a pipe: %s", ::strerror(errno)); + loggers::get_instance().error("pcap_layer::pcap_layer: Failed to create a pipe: '%s'", ::strerror(errno)); } if(online){ _pcap_h = _fd[0]; @@ -212,7 +212,7 @@ void pcap_layer::send_data(OCTETSTRING& data, params& params) { if (_pcap_h != -1) { // Check if offline mode is used if (pcap_sendpacket(_device, static_cast(data), data.lengthof()) == -1) { - loggers::get_instance().error("pcap_layer::send_data: Failed to send packet: %s", pcap_geterr(_device)); + loggers::get_instance().error("pcap_layer::send_data: Failed to send packet: '%s'", pcap_geterr(_device)); } } else if (_sent_file != NULL) { struct pcap_pkthdr hdr; diff --git a/ccsrc/Protocols/Pcap/pcap_linux_layer.cc b/ccsrc/Protocols/Pcap/pcap_linux_layer.cc index fecb2b3..ab9b5b8 100644 --- a/ccsrc/Protocols/Pcap/pcap_linux_layer.cc +++ b/ccsrc/Protocols/Pcap/pcap_linux_layer.cc @@ -42,7 +42,7 @@ pcap_layer::pcap_layer(const std::string &p_type, const std::string ¶m) params::const_iterator it; std::string nic; - loggers::get_instance().log(">>> pcap_layer::pcap_layer: %s, %s", to_string().c_str(), param.c_str()); + loggers::get_instance().log(">>> pcap_layer::pcap_layer: '%s', %s", to_string().c_str(), param.c_str()); // Setup parameters params::convert(_params, param); // Prepare capture processing @@ -69,7 +69,7 @@ pcap_layer::pcap_layer(const std::string &p_type, const std::string ¶m) } // else, continue // Set non-blocking flag for the polling procedure if (pcap_setnonblock(_device, 1, error_buffer) != 0) { - loggers::get_instance().error("pcap_layer::pcap_layer: Failed to set blocking mode: %s", error_buffer); + loggers::get_instance().error("pcap_layer::pcap_layer: Failed to set blocking mode: '%s'", error_buffer); } // Retrieve the device file handler _pcap_h = pcap_get_selectable_fd(_device); @@ -125,7 +125,7 @@ pcap_layer::pcap_layer(const std::string &p_type, const std::string ¶m) filter += std::string(" ") + it->second; } // Log final PCAP filter - loggers::get_instance().user("pcap_layer::pcap_layer: Filter: %s", filter.c_str()); + loggers::get_instance().user("pcap_layer::pcap_layer: Filter: '%s'", filter.c_str()); { struct bpf_program f = {0}; @@ -155,7 +155,7 @@ void pcap_layer::send_data(OCTETSTRING &data, params ¶ms) { loggers::get_instance().log_msg(">>> pcap_layer::send_data: ", data); if (pcap_sendpacket(_device, static_cast(data), data.lengthof()) == -1) { - loggers::get_instance().error("pcap_layer::send_data: Failed to send packet: %s", pcap_geterr(_device)); + loggers::get_instance().error("pcap_layer::send_data: Failed to send packet: '%s'", pcap_geterr(_device)); } } diff --git a/ccsrc/Protocols/Pcap/pcap_offline_layer.cc b/ccsrc/Protocols/Pcap/pcap_offline_layer.cc index d8afc3a..b84cfc2 100644 --- a/ccsrc/Protocols/Pcap/pcap_offline_layer.cc +++ b/ccsrc/Protocols/Pcap/pcap_offline_layer.cc @@ -33,7 +33,7 @@ typedef struct timeval pcap_o_timeval; pcap_offline_layer::pcap_offline_layer(const std::string &p_type, const std::string ¶m) : layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _running(FALSE), _time_key("pcap_offline_layer::Handle_Fd_Event_Readable") { - loggers::get_instance().log(">>> pcap_offline_layer::pcap_offline_layer: %s, %s", p_type.c_str(), param.c_str()); + loggers::get_instance().log(">>> pcap_offline_layer::pcap_offline_layer: '%s', %s", p_type.c_str(), param.c_str()); params::convert(_params, param); _o_params.insert(std::pair(std::string("timestamp"), std::string())); @@ -58,7 +58,7 @@ pcap_offline_layer::pcap_offline_layer(const std::string &p_type, const std::str if ((it != _params.end()) && !it->second.empty()) { const std::string &filter = it->second; // Log final PCAP filter - loggers::get_instance().user("pcap_offline_layer::pcap_offline_layer: Filter: %s", filter.c_str()); + loggers::get_instance().user("pcap_offline_layer::pcap_offline_layer: Filter: '%s'", filter.c_str()); struct bpf_program f = {0}; if (pcap_compile(_device, &f, filter.c_str(), 1, PCAP_NETMASK_UNKNOWN) != 0) { loggers::get_instance().error("pcap_offline_layer::pcap_offline_layer: Failed to compile PCAP filter"); @@ -72,7 +72,7 @@ pcap_offline_layer::pcap_offline_layer(const std::string &p_type, const std::str // create pipe and run thread if (pipe2(_fd, O_NONBLOCK) == -1) { - loggers::get_instance().error("pcap_offline_layer::pcap_offline_layer: Failed to create a pipe: %s", ::strerror(errno)); + loggers::get_instance().error("pcap_offline_layer::pcap_offline_layer: Failed to create a pipe: '%s'", ::strerror(errno)); } // Pass the pipe handler to the polling procedure loggers::get_instance().log("pcap_offline_layer::pcap_offline_layer: Call handler with descriptor %d", _fd[0]); diff --git a/ccsrc/Protocols/Tcp/tcp_layer.cc b/ccsrc/Protocols/Tcp/tcp_layer.cc index 18dea58..945a148 100644 --- a/ccsrc/Protocols/Tcp/tcp_layer.cc +++ b/ccsrc/Protocols/Tcp/tcp_layer.cc @@ -9,7 +9,7 @@ #include "loggers.hh" tcp_layer::tcp_layer(const std::string & p_type, const std::string & param) : layer(p_type), SSL_Socket(), PORT(p_type.c_str()), _params(), _client_id{-1}, _time_key("tcp_layer::Handle_Fd_Event_Readable"), _reconnect_on_send{false} { - loggers::get_instance().log(">>> tcp_layer::tcp_layer (1): %s, %s", to_string().c_str(), param.c_str()); + loggers::get_instance().log(">>> tcp_layer::tcp_layer (1): '%s', %s", to_string().c_str(), param.c_str()); // Setup parameters params::convert(_params, param); _params.log(); @@ -17,7 +17,7 @@ tcp_layer::tcp_layer(const std::string & p_type, const std::string & param) : la init(); } tcp_layer::tcp_layer(const std::string & p_type, const params & param) : layer(p_type), SSL_Socket(), PORT(p_type.c_str()), _params(), _client_id{-1}, _time_key("tcp_layer::Handle_Fd_Event_Readable"), _reconnect_on_send{false} { - loggers::get_instance().log(">>> tcp_layer::tcp_layer (2): %s", to_string().c_str()); + loggers::get_instance().log(">>> tcp_layer::tcp_layer (2): '%s'", to_string().c_str()); // Setup parameters _params = param; @@ -50,7 +50,7 @@ void tcp_layer::init() { _params.insert(std::pair(std::string("server"), "127.0.0.1")); // TODO Try using params::server instead of std::string("server") } if (!parameter_set(params::server.c_str(), _params[params::server].c_str())) { - loggers::get_instance().warning("tcp_layer::set_parameter: Unprocessed parameter: %s", params::server.c_str()); + loggers::get_instance().warning("tcp_layer::set_parameter: Unprocessed parameter: '%s'", params::server.c_str()); } bool ssl_mode = false; it = _params.find(params::use_ssl); @@ -70,7 +70,7 @@ void tcp_layer::init() { } } if (!parameter_set(remote_port_name(), _params[params::port].c_str())) { - loggers::get_instance().warning("tcp_layer::set_parameter: Unprocessed parameter: %s", params::port.c_str()); + loggers::get_instance().warning("tcp_layer::set_parameter: Unprocessed parameter: '%s'", params::port.c_str()); } it = _params.find(params::local_port); if (it == _params.cend()) { @@ -81,7 +81,7 @@ void tcp_layer::init() { } } if (!parameter_set(local_port_name(), _params[params::local_port].c_str())) { - loggers::get_instance().warning("tcp_layer::set_parameter: Unprocessed parameter: %s", params::local_port.c_str()); + loggers::get_instance().warning("tcp_layer::set_parameter: Unprocessed parameter: '%s'", params::local_port.c_str()); } parameter_set(use_connection_ASPs_name(), (!server_mode) ? "yes" : "no"); @@ -138,7 +138,7 @@ void tcp_layer::init() { parameter_set(client_TCP_reconnect_name(), "yes"); if (server_mode == 0) { - loggers::get_instance().log("tcp_layer::init: Establish connection: %s/%s", _params[params::server].c_str(), _params[params::port].c_str()); + loggers::get_instance().log("tcp_layer::init: Establish connection: '%s'/%s", _params[params::server].c_str(), _params[params::port].c_str()); open_client_connection(_params[params::server].c_str(), _params[params::port].c_str(), NULL, NULL); } } @@ -170,12 +170,12 @@ void tcp_layer::send_data(OCTETSTRING& data, params& params) { loggers::get_instance().log_msg(">>> tcp_layer::send_data: ", data); loggers::get_instance().log("tcp_layer::send_data: SSL mode: %x", get_ssl_use_ssl()); - loggers::get_instance().log("tcp_layer::send_data: server_mode: %s", _params[params::server_mode].c_str()); + loggers::get_instance().log("tcp_layer::send_data: server_mode: '%s'", _params[params::server_mode].c_str()); loggers::get_instance().log("tcp_layer::send_data: peer_list_get_nr_of_peers: %d", peer_list_get_nr_of_peers()); if ((_params[params::server_mode].compare("0") == 0) && (peer_list_get_nr_of_peers() == 0)) { // Reconnect (e.g. HTTP connection lost - loggers::get_instance().log("tcp_layer::send_data: Re-establish connection: %s/%s", _params[params::server].c_str(), _params[params::port].c_str()); + loggers::get_instance().log("tcp_layer::send_data: Re-establish connection: '%s'/%s", _params[params::server].c_str(), _params[params::port].c_str()); open_client_connection(_params[params::server].c_str(), _params[params::port].c_str(), NULL, NULL); } send_outgoing(static_cast(data), data.lengthof(), _client_id); diff --git a/ccsrc/Protocols/UDP/udp_layer.cc b/ccsrc/Protocols/UDP/udp_layer.cc index 04a6737..b44d382 100644 --- a/ccsrc/Protocols/UDP/udp_layer.cc +++ b/ccsrc/Protocols/UDP/udp_layer.cc @@ -14,7 +14,7 @@ udp_layer::udp_layer(const std::string &p_type, const std::string ¶m) : layer(p_type), PORT(p_type.c_str()), _params(), _saddr{0}, _daddr{0}, _reuse_incoming_source_adddress(false), _fd(-1), _time_key("udp_layer::Handle_Fd_Event_Readable") { - loggers::get_instance().log(">>> udp_layer::udp_layer (1): %s, %s, %p", to_string().c_str(), param.c_str(), (void*)this); + loggers::get_instance().log(">>> udp_layer::udp_layer (1): '%s', %s, %p", to_string().c_str(), param.c_str(), (void*)this); // Setup parameters params::convert(_params, param); @@ -25,7 +25,7 @@ udp_layer::udp_layer(const std::string &p_type, const std::string ¶m) udp_layer::udp_layer(const std::string &p_type, const params ¶m) : layer(p_type), PORT(p_type.c_str()), _params(), _saddr{0}, _daddr{0}, _reuse_incoming_source_adddress(false), _fd(-1), _time_key("udp_layer::Handle_Fd_Event_Readable") { - loggers::get_instance().log(">>> udp_layer::udp_layer (2): %s", to_string().c_str()); + loggers::get_instance().log(">>> udp_layer::udp_layer (2): '%s'", to_string().c_str()); // Setup parameters _params = param; @@ -148,7 +148,7 @@ void udp_layer::Handle_Fd_Event_Readable(int fd) { std::copy((unsigned char *)buffer, (unsigned char *)((unsigned char *)buffer + result), std::back_inserter(acc)); if (_reuse_incoming_source_adddress) { // Reuse the incoming address/port for sending memcpy((void *)&_daddr, (const void *)&from, sizeof(struct sockaddr_in)); - loggers::get_instance().log("udp_layer::Handle_Fd_Event_Readable: New _daddr: %s:%d", ::inet_ntoa(_daddr.sin_addr), ntohs(_daddr.sin_port)); + loggers::get_instance().log("udp_layer::Handle_Fd_Event_Readable: New _daddr: '%s':%d", ::inet_ntoa(_daddr.sin_addr), ntohs(_daddr.sin_port)); } } params.insert(std::pair( @@ -182,13 +182,13 @@ unsigned long udp_layer::get_host_id(const std::string &p_host_name) { struct hostent *hptr; if ((hptr = ::gethostbyname(p_host_name.c_str())) == 0) { close(); - loggers::get_instance().error("udp_layer::get_host_id: Invalid host name: %s", p_host_name.c_str()); + loggers::get_instance().error("udp_layer::get_host_id: Invalid host name: '%s'", p_host_name.c_str()); } ip_addr = *((unsigned long *)hptr->h_addr_list[0]); } } - loggers::get_instance().log("udp_layer::get_host_id: Host name: %s, Host address: %u", p_host_name.c_str(), ip_addr); + loggers::get_instance().log("udp_layer::get_host_id: Host name: '%s', Host address: %u", p_host_name.c_str(), ip_addr); return htonl(ip_addr); } diff --git a/ccsrc/Protocols/Xml/src/xml_converters.cc b/ccsrc/Protocols/Xml/src/xml_converters.cc index 363cc9a..014504d 100644 --- a/ccsrc/Protocols/Xml/src/xml_converters.cc +++ b/ccsrc/Protocols/Xml/src/xml_converters.cc @@ -18,7 +18,7 @@ xml_converters* xml_converters::_instance = nullptr; int xml_converters::xml_canonicalization(const std::string& p_to_canonical, std::string& p_canonicalized) const { - loggers::get_instance().log(">>> xml_converters::xml_canonicalization"); + loggers::get_instance().log(">>> xml_converters::xml_canonicalization: '%s'", p_to_canonical.c_str()); xmlDocPtr doc = xmlParseMemory(p_to_canonical.c_str(), p_to_canonical.length()); if (doc == nullptr) { @@ -52,7 +52,7 @@ int xml_converters::xml_canonicalization(const std::string& p_to_canonical, std: xmlOutputBufferClose(buffer); xmlFreeDoc(doc); - loggers::get_instance().log("<<< xml_converters::xml_canonicalization: %s", p_canonicalized.c_str()); + loggers::get_instance().log("<<< xml_converters::xml_canonicalization: '%s'", p_canonicalized.c_str()); return 0; } diff --git a/ccsrc/security/include/certs_cache.hh b/ccsrc/security/include/certs_cache.hh new file mode 100644 index 0000000..e51f5e6 --- /dev/null +++ b/ccsrc/security/include/certs_cache.hh @@ -0,0 +1,102 @@ +/*! + * \file certs_cache.hh + * \brief Header file for a certificates caching storage mechanism. + * It is used to store certificates received from neighbors and not present in the data base + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include +#include +#include +#include + +#include + +#include "certs_db_record.hh" + +/*! + * \class certs_cache + * \brief This class provides security record description for in memory security database. In memory mens there is no disk load/save mechanism + */ +class certs_cache { + static bool fill_vector(std::string& p_vector, const std::string& p_org); + +protected: /*! \protectedsection */ + // TODO Enforce with const security_cache_record, and const std::string + std::map _certificates_idx; //! List of the certificate names indexed by the certificate identifier, i.e. the SH1 of the certificate name + std::map> _certificates; //! List of the certificates indexed by the certificate identifier + +public: /*! \publicsection */ + /*! + * \brief Default ctor + */ + certs_cache(); + /*! + * \brief Default private dtor + */ + virtual ~certs_cache(); + + int get_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const X509** p_certificate); + /*! + * \fn int get_certificate(const std::string& p_hashed_id8, const X509** p_certificate); + * \brief Retrive the specified certificate either from memory + * \param[in] p_certificate_id The certificate name + * \param[out] p_certificate The X509 certificate + * \return 0 on success, -1 otherwise + */ + int get_certificate(const std::string& p_certificate_id, const X509** p_certificate); + /*! + * \fn int get_private_key(const std::string &p_certificate_id, const EVP_PKEY** p_private_key); + * \brief Retrive the private key of the specified certificate + * \param[in] p_certificate_id The certificate name + * \param[out] p_private_key The private key + * \return 0 on success, -1 otherwise + */ + int get_private_key(const std::string &p_certificate_id, const EVP_PKEY** p_private_key); + /*! + * \fn int get_public_keys(const std::string &p_certificate_id, const EVP_PKEY** p_public_key); + * \brief Retrive the public keys (in uncompressed format) of the specified certificate + * \param[in] p_certificate_id The certificate name + * \param[out] p_public_key The public key + * \return 0 on success, -1 otherwise + */ + int get_public_keys(const std::string &p_certificate_id, const EVP_PKEY** p_public_key); + + virtual int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key); + + /*! + * \fn int int clear(); + * \brief Cleanup the cache + * \return 0 on success, -1 otherwise + * \virtual + */ + virtual int clear(); + + void dump() const; + +private: /*! \privatesection */ + /*! + * \fn int load_certificate(const std::string &p_certificate_name, const std::string &p_private_key_name, const certs_db_record** p_record); + * \brief Retrive the specified certificate either from memory of from storage location + * \param[in] p_certificate_name The certificate name + * \param[in] p_private_key_name The certificate's private key name + * \param[out] p_record A reference to the certificate record + * \return 0 on success, -1 otherwise + */ + int load_certificate(const std::string &p_certificate_name, const std::string &p_private_key_name, const certs_db_record** p_record); + /*! + * \fn int load_certificate(const std::string& p_certificate_id, const certs_db_record** p_record); + * \brief Retrive the specified certificate either from memory of from storage location + * \param[in] p_certificate_id The certificate identifier + * \param[out] p_record A reference to the certificate record + * \return 0 on success, -1 otherwise + */ + int load_certificate(const std::string &p_certificate_id, const certs_db_record** p_record); + +}; // End of class certs_cache diff --git a/ccsrc/security/include/certs_db.hh b/ccsrc/security/include/certs_db.hh new file mode 100644 index 0000000..0f08fa4 --- /dev/null +++ b/ccsrc/security/include/certs_db.hh @@ -0,0 +1,49 @@ +/*! + * \file certs_db.hh + * \brief Header file for a list of certificates storage mechanism. + * It is used to store certificates received from neighbors and not present in the data base + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include "certs_cache.hh" + +/*! + * \class certs_db + * \brief This class provides security record description for security database + */ +class certs_db : public certs_cache { + +public: /*! \publicsection */ + /*! + * \brief Ctor with full path to the certificates storage + * \param[in] p_db_path The full path to the certificates storage + */ + certs_db(const std::string &p_db_path); + /*! + * \brief Default dtor + */ + ~certs_db(); + + /*! + * \fn int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key); + * \brief Store a new certificate + * \param[in] p_certificate_name The certificate name + * \return 0 on success, -1 otherwise + */ + int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key); + +private: /*! \privatesection */ + /*! + * \fn int initialize_cache(const std::string& p_db_path); + * \brief Initialise the storage of certificates mechanism + * \param[in] p_db_path The full path to the certificates storage + * \return 0 on success, -1 otherwise + */ + int initialize_cache(const std::string &p_db_path); +}; // End of class certs_db diff --git a/ccsrc/security/include/certs_db_record.hh b/ccsrc/security/include/certs_db_record.hh new file mode 100644 index 0000000..f98f82a --- /dev/null +++ b/ccsrc/security/include/certs_db_record.hh @@ -0,0 +1,62 @@ +/*! + * \file certs_db_record.hh + * \brief Header file for a storage of certificates mechanism. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include + +#include + +/*! + * \class certs_db_record + * \brief This class provides security record description for security database + */ +class certs_db_record { + + std::string _certificate_id; /*!< Certificate name */ + X509* _certificate; /*!< X509 Certificate */ + EVP_PKEY* _private_key; /*!< Private key */ + +public: /*! \publicsection */ + /*! + * \brief Default ctor + */ + explicit certs_db_record() + : _certificate_id(nullptr), _certificate(nullptr), _private_key(nullptr) {}; + /*! + * \brief Specialised ctor + * \param[in] p_certificate_id The certificate identifier + * \param[in] p_certificate The X509 certificate in openssl format + * \param[in] p_private_key The certificate's private key in openssl format + */ + certs_db_record(const std::string &p_certificate_id, X509* p_certificate, EVP_PKEY* p_private_key); + + /*! + * \brief Default dtor + */ + ~certs_db_record(); + + /*! + * \inline + * \fn const std::string& certificate_id() const; + * \brief Retrieve the certificate identifier value + * \return The certificate identifier + */ + inline const std::string &certificate_id() const { return _certificate_id; }; + /*! + * \inline + * \fn const X509* certificate() const; + * \brief Retrieve the COER encoded certificate + * \return The COER encoded certificate + */ + inline const X509* certificate() const { return _certificate; }; + inline const EVP_PKEY* private_key() const { return _private_key; }; + inline const EVP_PKEY* public_key() const { return ::X509_get_pubkey(_certificate); }; +}; // End of class certs_db_record diff --git a/ccsrc/security/include/certs_loader.hh b/ccsrc/security/include/certs_loader.hh new file mode 100644 index 0000000..42fd162 --- /dev/null +++ b/ccsrc/security/include/certs_loader.hh @@ -0,0 +1,97 @@ +/*! + * \file certs_loader.hh + * \brief Header file for X506 PEM certificates loader definition. + * \author ETSI STF625 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + * \remark Use `openssl x509 -in -noout -text` to view the certficate content + * Use `openssl [rsa|dsa|...] -inform PEM -in -text -noout` to view the private key content + * Use `openssl x509 -in -out ` to convert a DER certificate into a PEM certificate + */ +#pragma once + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "certs_db_record.hh" + +/*! + * \class certs_loader + * \brief This class provides mechanism to load the certificates from the filesystem according the struecture defined in ETSI TS 103 099 + * \remark Singleton pattern + */ +class certs_loader { + std::experimental::filesystem::path _db_path; //! Path of the certificates storage + bool _is_cache_initialized; //! Set to true when certificates are successfully loaded from file system + static certs_loader* instance; //! Unique static object reference of this class + + /*! + * \brief Default private ctor + */ + certs_loader(); + /*! + * \brief Default private dtor + */ + ~certs_loader() { + if (instance != NULL) { + delete instance; + instance = NULL; + } + }; + +public: /*! \publicsection */ + /*! + * \brief Public accessor to the single object reference + */ + inline static certs_loader &get_instance() { + if (instance == NULL) + instance = new certs_loader(); + return *instance; + }; + + /*! + * \fn int build_path(const std::string &p_root_directory); + * \brief Set the pass of the certificate storage + * \param[in] p_db_path The pass of the certificate storage + */ + int build_path(const std::string& p_root_directory); + /*! + * \fn int get_certificate_id(const std::string& p_certificate_name, std::string& p_certificate_id); + * \brief Compute the SHA-1 hash of the certificate name to provide the certificate identifier + * \param[in] p_certificate_name The certificate name + * \param[out] p_certificate_id The certificate identifier + * \return 0 on success, -1 otherwise + */ + int get_certificate_id(const std::string& p_certificate_name, std::string& p_certificate_id); + /*! + * \fn int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, std::map> & p_certificates); + * \brief Store in memory the specified certificate + * \param[in] p_certificate_name The certificate full path bame + * \param[in] p_private_key_name The certificate's private key full path name + * \param[out] p_certificate_id The certificate identifier + * \param[inout] p_certificates The map of the loaded in memory certificates + * \return 0 on success, -1 otherwise + */ + int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, std::string& p_certificate_id, std::map> & p_certificates); + /*! + * \fn int save_certificate(const certs_db_record &p_certificate); + * \brief Save the specified certificate and update the internal maps + * \param[in] p_certificate The certificate to save + * \param[out] p_certificate_id The certificate identifier + * \return 0 on success, -1 otherwise + */ + int save_certificate(const certs_db_record &p_certificate, std::string& p_certificate_id); +}; // End of class certs_loader + diff --git a/ccsrc/security/include/hmac.hh b/ccsrc/security/include/hmac.hh new file mode 100644 index 0000000..cbd1ccd --- /dev/null +++ b/ccsrc/security/include/hmac.hh @@ -0,0 +1,69 @@ +/*! + * \file hmac.hh + * \brief Header file for HMAC helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include + +#include + +class OCTETSTRING; //! TITAN forward declaration + +/*! + * \enum Supported hash algorithms + */ +enum class hash_algorithms : unsigned char { + sha_256, /*!< HMAC with SHA-256 */ + sha_384 /*!< HMAC with SHA-384 */ +}; // End of class hash_algorithms + +/*! + * \class hmac + * \brief This class provides description of HMAC helper methods + */ +class hmac { + HMAC_CTX * _ctx; //! HMAC context + hash_algorithms _hash_algorithms; //! HMAC hash algorithm to use +public: + /*! + * \brief Default constructor + * Create a new instance of the hmac class + * \param[in] p_hash_algorithms The hash algorithm to be used to compute the HMAC. Default: sha_256 + */ + hmac(const hash_algorithms p_hash_algorithms = hash_algorithms::sha_256) : _ctx{::HMAC_CTX_new()}, _hash_algorithms(p_hash_algorithms){}; + /*! + * \brief Default destructor + */ + virtual ~hmac() { + if (_ctx != nullptr) { + ::HMAC_CTX_free(_ctx); + }; + }; + + /*! + * \fn int generate(const OCTETSTRING p_buffer, const OCTETSTRING p_secret_key, OCTETSTRING& p_hmac); + * \brief Generate the HMAC of data using a secret key + * \Param[in] p_buffer The data tobe hashed + * \param[in] p_secret_key The secret key to be used to generate the HMAC + * \param[out] p_hmac The HMAC value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const OCTETSTRING p_buffer, const OCTETSTRING p_secret_key, OCTETSTRING &p_hmac); // TODO Use reference & + + /*! + * \fn int generate(const unsigned char* p_buffer, const size_t p_buffer_length, const unsigned char* p_secret_key, const size_t p_secret_key_length, + * OCTETSTRING& p_hmac); \brief Generate the HMAC of data using a secret key \param[in] p_buffer The data to be hashed \param[in] p_buffer_length The size of + * the data \param[in] p_secret_key The secret key to be used to generate the HMAC \param[in] p_secret_key_length The size of the secret key \param[out] + * p_hmac The HMAC value based of the provided data \return 0 on success, -1 otherwise + */ + int generate(const unsigned char *p_buffer, const size_t p_buffer_length, const unsigned char *p_secret_key, const size_t p_secret_key_length, + OCTETSTRING &p_hmac); + +}; // End of class hmac diff --git a/ccsrc/security/include/security_services.hh b/ccsrc/security/include/security_services.hh new file mode 100644 index 0000000..99bfb5f --- /dev/null +++ b/ccsrc/security/include/security_services.hh @@ -0,0 +1,40 @@ +#pragma once + +#include + +#include +#include +#include + +#include "certs_db.hh" + +class CHARSTRING; +class OCTETSTRING; + + +class security_services { + /*std::unique_ptr _certs_db*/; + static certs_db* _certs_db; + +public: /*! \publicsection */ + /*! + * \brief Default private ctor + */ + security_services()/* : _certs_db{nullptr}*/ {}; + /*! + * \brief Default private dtor + */ + ~security_services() { + //_certs_db.reset(); + delete _certs_db; + }; + + int initialize(const std::string& p_certs_db_path); + int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const X509** p_certificate); + /*! + * \fn int build_path(const std::string &p_root_directory); + * \brief Set the pass of the certificate storage + * \param[in] p_db_path The pass of the certificate storage + */ + int do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem); +}; \ No newline at end of file diff --git a/ccsrc/security/include/sha1.hh b/ccsrc/security/include/sha1.hh new file mode 100644 index 0000000..69f35da --- /dev/null +++ b/ccsrc/security/include/sha1.hh @@ -0,0 +1,66 @@ +/*! + * \file sha1.hh + * \brief Header file for SHA-1 helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include +#include + +class OCTETSTRING; //! TITAN forward declaration + +/*! + * \class sha1 + * \brief This class provides description of SHA-1 helper methods + */ +class sha1 { + SHA_CTX _ctx; //! SHA context +public: + /*! + * \brief Default constructor + * Create a new instance of the sha1 class + */ + explicit sha1() : _ctx{} {}; + /*! + * \brief Default destructor + */ + virtual ~sha1(){}; + + /*! + * \fn int generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The data used to generate the SHA-1 hash + * \param[out] p_hash The SHA-1 hash value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash); + + /*! + * \fn int generate(const unsigned char* p_buffer, OCTETSTRING& p_hash); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The data used to generate the SHA-1 hash + * \param[in] The length of the data buffer + * \param[out] p_hash The SHA-1 hash value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash); + + /*! + * \fn const OCTETSTRING get_sha1_empty_string() const; + * \brief Return the SHA-1 of an empty string + * \return The SHA-1 of an empty string + */ + inline const OCTETSTRING get_sha1_empty_string() const { + static unsigned char sha1_empty_string[] = { + 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, + 0xaf, 0xd8, 0x07, 0x09}; //! SHA-1 of an empty string + return OCTETSTRING(20, sha1_empty_string); + }; + +}; // End of class sha1 diff --git a/ccsrc/security/include/sha256.hh b/ccsrc/security/include/sha256.hh new file mode 100644 index 0000000..fbb972d --- /dev/null +++ b/ccsrc/security/include/sha256.hh @@ -0,0 +1,66 @@ +/*! + * \file sha256.hh + * \brief Header file for SHA-256 helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include +#include + +class OCTETSTRING; //! TITAN forward declaration + +/*! + * \class sha256 + * \brief This class provides description of SHA-256 helper methods + */ +class sha256 { + SHA256_CTX _ctx; //! SHA context +public: + /*! + * \brief Default constructor + * Create a new instance of the sha256 class + */ + explicit sha256() : _ctx{} {}; + /*! + * \brief Default destructor + */ + virtual ~sha256(){}; + + /*! + * \fn int generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The data used to generate the SHA-256 hash + * \param[out] p_hash The SHA-256 hash value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash); + + /*! + * \fn int generate(const unsigned char* p_buffer, OCTETSTRING& p_hash); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The data used to generate the SHA-256 hash + * \param[in] The length of the data buffer + * \param[out] p_hash The SHA-256 hash value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash); + + /*! + * \fn const OCTETSTRING get_sha256_empty_string() const; + * \brief Return the SHA-256 of an empty string + * \return The SHA-256 of an empty string + */ + inline const OCTETSTRING get_sha256_empty_string() const { + static unsigned char sha256_empty_string[] = { + 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; //! SHA-256 of an empty string + return OCTETSTRING(32, sha256_empty_string); + }; + +}; // End of class sha256 diff --git a/ccsrc/security/include/sha384.hh b/ccsrc/security/include/sha384.hh new file mode 100644 index 0000000..016c54f --- /dev/null +++ b/ccsrc/security/include/sha384.hh @@ -0,0 +1,60 @@ +/*! + * \file sha384.hh + * \brief Header file for SHA-384 helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include +#include + +class OCTETSTRING; //! TITAN forward declaration + +/*! + * \class sha384 + * \brief This class provides description of SHA-384 helper methods + */ +class sha384 { + SHA512_CTX _ctx; //! SHA context +public: //! \publicsection + /*! + * \brief Default constructor + * Create a new instance of the sha384 class + */ + explicit sha384() : _ctx{} {}; + /*! + * \brief Default destructor + */ + virtual ~sha384(){}; + + /*! + * \fn int generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The data used to generate the SHA-384 hash + * \param[out] p_hash The SHA-384 hash value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash); + + /*! + * \fn int generate(const OCTETSTRING p_buffer, OCTETSTRING& p_hash); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The data used to generate the SHA-384 hash + * \param[in] The length of the data buffer + * \param[out] p_hash The SHA-384 hash value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash); + + /*! + * \fn const OCTETSTRING get_sha384_empty_string() const; + * \brief Return the SHA-384 of an empty string + * \return The SHA-384 of an empty string + */ + const OCTETSTRING get_sha384_empty_string() const; +}; // End of class sha384 diff --git a/ccsrc/security/module.mk b/ccsrc/security/module.mk new file mode 100644 index 0000000..ac2c199 --- /dev/null +++ b/ccsrc/security/module.mk @@ -0,0 +1,13 @@ +sources := \ + src/security_externals.cc \ + src/sha1.cc \ + src/sha256.cc \ + src/sha384.cc \ + src/hmac.cc \ + src/certs_db_record.cc \ + src/certs_db.cc \ + src/certs_cache.cc \ + src/certs_loader.cc \ + src/securty_services.cc + +includes := ./include diff --git a/ccsrc/security/src/certs_cache.cc b/ccsrc/security/src/certs_cache.cc new file mode 100644 index 0000000..b0b413a --- /dev/null +++ b/ccsrc/security/src/certs_cache.cc @@ -0,0 +1,152 @@ +/*! + * \file certs_cache.cc + * \brief Source file for a certificates caching storage mechanism. + * It is used to store certificates received from neighbors and not present in the data base + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#include "certs_cache.hh" +#include "certs_loader.hh" + +#include "TTCN3.hh" +#include "sha1.hh" + +#include "converter.hh" + +#include "loggers.hh" + +certs_cache::certs_cache() : _certificates_idx(), _certificates() { loggers::get_instance().log(">>> certs_cache::certs_cache"); } // End of ctor + +certs_cache::~certs_cache() { + loggers::get_instance().log(">>> certs_cache::~certs_cache"); + clear(); +} // End of dtor + +int certs_cache::clear() { + loggers::get_instance().log(">>> certs_cache::clear"); + _certificates.clear(); // Smart pointers will do the job + _certificates_idx.clear(); + + return 0; +} // End of clear method + +int certs_cache::load_certificate(const std::string &p_certificate_id, const certs_db_record** p_record) { + loggers::get_instance().log(">>> certs_cache::load_certificate (1): '%s'", p_certificate_id.c_str()); + + // Sanity check + std::map>::const_iterator it = _certificates.find(p_certificate_id); + if (it == _certificates.cend()) { + loggers::get_instance().warning("certs_cache::load_certificate: Failed to load certificate"); + return -1; + } + + *p_record = it->second.get(); + + return 0; +} + +int certs_cache::load_certificate(const std::string &p_certificate_name, const std::string &p_private_key_name, const certs_db_record** p_record) { + loggers::get_instance().log(">>> certs_cache::load_certificate (2): '%s'", p_certificate_name.c_str()); + + std::string certificate_id; + if (certs_loader::get_instance().get_certificate_id(p_certificate_name, certificate_id) != 0) { + loggers::get_instance().warning("certs_cache::load_certificate: Failed to retrieve certificate identifier"); + return -1; + } + loggers::get_instance().log("certs_cache::load_certificate (2): certificate_id: '%s'", certificate_id.c_str()); + + std::map::const_iterator s = _certificates_idx.find(certificate_id); + if (s == _certificates_idx.cend()) { // Certificate is not in the DB + loggers::get_instance().log("certs_cache::load_certificate (2): Record not found"); + if (certs_loader::get_instance().load_certificate(p_certificate_name, p_private_key_name, certificate_id, _certificates) == -1) { + loggers::get_instance().warning("certs_cache::load_certificate: Failed to load certificate"); + return -1; + } + // Mapping certificate id/certificate name + _certificates_idx.insert(std::pair(certificate_id, p_certificate_name)); + } + + // Certificate is on the DB, load it if required + std::map>::const_iterator it = _certificates.find(certificate_id); + *p_record = it->second.get(); + + return 0; +} + +int certs_cache::get_certificate(const std::string& p_certificate_name, const std::string &p_private_key_name, const X509** p_certificate) { + loggers::get_instance().log(">>> certs_cache::get_certificate (1): '%s'", p_certificate_name.c_str()); + + const certs_db_record* record; + if (load_certificate(p_certificate_name, p_private_key_name, &record) == -1) { + loggers::get_instance().warning("certs_cache::get_certificate (1): Failed to load certificate"); + return -1; + } + + *p_certificate = record->certificate(); + loggers::get_instance().log("certs_cache::get_certificate (1): p_certificate: '%p'", *p_certificate); + + return 0; +} + +int certs_cache::get_certificate(const std::string &p_certificate_id, const X509** p_certificate) { + loggers::get_instance().log(">>> certs_cache::get_certificate (2): '%s'", p_certificate_id.c_str()); + + const certs_db_record* record; + if (load_certificate(p_certificate_id, &record) == -1) { + loggers::get_instance().warning("certs_cache::get_certificate (2): Failed to load certificate"); + return -1; + } + + *p_certificate = record->certificate(); + loggers::get_instance().log("certs_cache::get_certificate (2): p_certificate: '%p'", *p_certificate); + + return 0; +} + +int certs_cache::get_private_key(const std::string &p_certificate_id, const EVP_PKEY** p_private_key) { + loggers::get_instance().log(">>> certs_cache::get_private_key: '%s'", p_certificate_id.c_str()); + + const certs_db_record *record; + if (load_certificate(p_certificate_id, &record) == -1) { + loggers::get_instance().warning("certs_cache::get_private_key: Failed to load certificate"); + return -1; + } + + *p_private_key = record->private_key(); + loggers::get_instance().log("certs_cache::get_private_key: p_private_key: '%p'", *p_private_key); + + return 0; +} + +int certs_cache::get_public_keys(const std::string &p_certificate_id, const EVP_PKEY** p_public_key) { + loggers::get_instance().log(">>> certs_cache::get_public_keys: '%s'", p_certificate_id.c_str()); + + const certs_db_record* record; + if (load_certificate(p_certificate_id, &record) == -1) { + loggers::get_instance().warning("certs_cache::get_public_keys: Failed to load certificate"); + return -1; + } + + *p_public_key = record->public_key(); + loggers::get_instance().log("certs_cache::p_public_key: p_public_key: '%p'", *p_public_key); + + return 0; +} + +int certs_cache::store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key) { + loggers::get_instance().log(">>> certs_cache::store_certificate: '%s'", p_certificate_name.c_str()); + + return -1; +} + +void certs_cache::dump() const { + loggers::get_instance().log("certs_cache::dump_certificates: # items = %d", _certificates.size()); + + for (std::map>::const_iterator it = _certificates.cbegin(); it != _certificates.cend(); ++it) { + const certs_db_record *p = it->second.get(); + } // End of 'for' statement +} // End of method dump diff --git a/ccsrc/security/src/certs_db.cc b/ccsrc/security/src/certs_db.cc new file mode 100644 index 0000000..0555519 --- /dev/null +++ b/ccsrc/security/src/certs_db.cc @@ -0,0 +1,32 @@ +#include "certs_db.hh" + +#include "params.hh" +#include "loggers.hh" +#include "converter.hh" + +using namespace std; // Required for isnan() +#include "certs_loader.hh" + +certs_db::certs_db(const std::string &p_db_path) { + loggers::get_instance().log(">>> certs_db::certs_db: '%s'", p_db_path.c_str()); + + initialize_cache(p_db_path); + loggers::get_instance().log("<<< certs_db::certs_db"); +} // End of ctor + +certs_db::~certs_db() { loggers::get_instance().log(">>> certs_db::~certs_db"); } // End of dtor + +int certs_db::initialize_cache(const std::string &p_db_path) { + loggers::get_instance().log(">>> certs_db::initialize_cache: '%s'", p_db_path.c_str()); + + certs_loader::get_instance().build_path(p_db_path); + + loggers::get_instance().log("<<< certs_db::initialize_cache"); + return 0; +} + +int certs_db::store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key) { + loggers::get_instance().log(">>> certs_db::store_certificate: '%s'", p_certificate_name.c_str()); + + return -1; +} diff --git a/ccsrc/security/src/certs_db_record.cc b/ccsrc/security/src/certs_db_record.cc new file mode 100644 index 0000000..59a0bd1 --- /dev/null +++ b/ccsrc/security/src/certs_db_record.cc @@ -0,0 +1,29 @@ +/*! + * \file certs_db_record.cc + * \brief Source file for a storage of certificates mechanism. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ + +#include + +#include "loggers.hh" + +#include "certs_db_record.hh" + +certs_db_record::certs_db_record(const std::string &p_certificate_id, X509* p_certificate, EVP_PKEY* p_private_key) : _certificate_id(p_certificate_id), _certificate(p_certificate), _private_key(p_private_key) { + loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_certificate_id: '%s'", p_certificate_id.c_str()); + loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_certificate: '%p'", p_certificate); + loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_private_key: '%p'", p_private_key); +} + +certs_db_record::~certs_db_record() { + if (_certificate != nullptr) { + ::X509_free(_certificate); + ::EVP_PKEY_free(_private_key); + } +} diff --git a/ccsrc/security/src/certs_loader.cc b/ccsrc/security/src/certs_loader.cc new file mode 100644 index 0000000..dcb4b77 --- /dev/null +++ b/ccsrc/security/src/certs_loader.cc @@ -0,0 +1,143 @@ +#include +#include + +#include +#include +#include +#include + +#include + +#include "sha1.hh" +#include "certs_loader.hh" + +#include "loggers.hh" + +certs_loader *certs_loader::instance = nullptr; + +certs_loader::certs_loader() : _db_path(), _is_cache_initialized{false} { + loggers::get_instance().log(">>> certs_loader::certs_loader"); +} // End of ctor + +int certs_loader::build_path(const std::string& p_root_directory) { + loggers::get_instance().log(">>> certs_loader::build_path: '%s'", p_root_directory.c_str()); + + // Sanity check + if (_is_cache_initialized) { + return 0; + } + + // Build full path + if (!p_root_directory.empty()) { + _db_path = p_root_directory; + if (!std::experimental::filesystem::exists(_db_path) || + !std::experimental::filesystem::is_directory(_db_path)) { // FIXME Coredump when app hasn't the rights to create the directory!!!! + // Create directory + if (!std::experimental::filesystem::create_directory(_db_path)) { + _db_path = "./"; + } else { // Set rights for all users + std::experimental::filesystem::permissions(_db_path, + std::experimental::filesystem::perms::add_perms | std::experimental::filesystem::perms::owner_all | + std::experimental::filesystem::perms::group_all | std::experimental::filesystem::perms::others_all); + } + } + } else { + _db_path = "./"; + } + std::experimental::filesystem::canonical(_db_path); + loggers::get_instance().log("certs_loader::build_path: full path: %s", _db_path.string().c_str()); + if (!std::experimental::filesystem::exists(_db_path)) { + loggers::get_instance().warning("certificates_loader::build_path: Invalid path"); + _db_path.clear(); + return -1; + } + + + loggers::get_instance().log("<<< certs_loader::build_path"); + return 0; +} + +int certs_loader::get_certificate_id(const std::string& p_certificate_name, std::string& p_certificate_id) { + loggers::get_instance().log(">>> certs_loader::get_certificate_id: '%s'", p_certificate_name.c_str()); + + // Build the certificate identifier + sha1 s; + const OCTETSTRING buffer = OCTETSTRING(p_certificate_name.length(), (unsigned char*)p_certificate_name.c_str()); + OCTETSTRING hash; + if (s.generate(buffer, hash) != 0) { + loggers::get_instance().warning("certs_cache::load_certificate: Failed to build the certificate identifier"); + return -1; + } + loggers::get_instance().log_msg("certs_loader::get_certificate_id: hash: ", hash); + CHARSTRING hash_str = oct2str(hash); + p_certificate_id.assign(static_cast(hash_str), static_cast(hash_str) + hash_str.lengthof()); + + loggers::get_instance().log("<<< certs_loader::get_certificate_id: '%s'", p_certificate_id.c_str()); + return 0; +} + +int certs_loader::load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, std::string& p_certificate_id, std::map> & p_certificates) { + loggers::get_instance().log(">>> certs_loader::load_certificate %s", p_certificate_name.c_str()); + loggers::get_instance().log(">>> certs_loader::load_certificate: '%s'", p_private_key_name.c_str()); + + // Load certificate file + BIO* certbio = ::BIO_new(::BIO_s_file()); + if (certbio == nullptr) { + loggers::get_instance().warning("certs_loader::load_certificate: Error creating BIO"); + return -1; + } + std::experimental::filesystem::path p = _db_path.string() + "/" + p_certificate_name; + int ret = BIO_read_filename(certbio, p.string().c_str()); + X509* cert = ::PEM_read_bio_X509(certbio, NULL, 0, NULL); + if (cert == nullptr) { + loggers::get_instance().warning("certs_loader::load_certificate: Error loading cert into memory"); + ::BIO_free_all(certbio); + return -1; + } + ::BIO_free_all(certbio); + + // Load private key file + certbio = ::BIO_new(::BIO_s_file()); + if (certbio == nullptr) { + loggers::get_instance().warning("certs_loader::load_certificate: Error creating BIO"); + ::X509_free(cert); + return -1; + } + p = _db_path.string() + "/" + p_private_key_name; + ret = BIO_read_filename(certbio, p.string().c_str()); + EVP_PKEY* private_key = ::PEM_read_bio_PrivateKey(certbio, NULL, 0, NULL); + if (private_key == nullptr) { + loggers::get_instance().warning("certs_loader::load_certificate: Error loading cert into memory"); + ::X509_free(cert); + ::BIO_free_all(certbio); + return -1; + } + ::BIO_free_all(certbio); + + // Build the certificate identifier + if (get_certificate_id(p_certificate_name, p_certificate_id) != 0) { + loggers::get_instance().warning("certs_cache::load_certificate: Failed to build the certificate identifier"); + return -1; + } + loggers::get_instance().log("certs_loader::load_certificate: p_certificate_name: '%s'", p_certificate_name.c_str()); + loggers::get_instance().log("certs_loader::load_certificate: p_certificate_id: '%s'", p_certificate_id.c_str()); + loggers::get_instance().log("certs_loader::load_certificate: cert: '%p'", cert); + loggers::get_instance().log("certs_loader::load_certificate: private_key: '%p'", private_key); + + // Create new record + certs_db_record *r = new certs_db_record(p_certificate_name, cert, private_key); + std::pair>::iterator, bool> result = p_certificates.insert(std::pair>(p_certificate_id, std::unique_ptr(r))); + if (result.second == false) { + loggers::get_instance().warning("certs_loader::build_certificates_cache: Failed to insert new record '%s'", p_certificate_name.c_str()); + delete r; + return -1; + } + + return 0; +} + +int certs_loader::save_certificate(const certs_db_record &p_certificate, std::string& p_certificate_id) { + + return -1; +} // End of method save_certificate + diff --git a/ccsrc/security/src/hmac.cc b/ccsrc/security/src/hmac.cc new file mode 100644 index 0000000..ab5c248 --- /dev/null +++ b/ccsrc/security/src/hmac.cc @@ -0,0 +1,54 @@ +/*! + * \file hmac.cc + * \brief Source file for HMAC helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#include + +#include "hmac.hh" + +#include "loggers.hh" + +int hmac::generate(const OCTETSTRING p_buffer, const OCTETSTRING p_secret_key, OCTETSTRING &p_hmac) { + // Sanity check + if (p_buffer.lengthof() == 0) { + return -1; + } + + return generate(static_cast(p_buffer), p_buffer.lengthof(), static_cast(p_secret_key), p_secret_key.lengthof(), + p_hmac); +} + +int hmac::generate(const unsigned char *p_buffer, const size_t p_buffer_length, const unsigned char *p_secret_key, const size_t p_secret_key_length, + OCTETSTRING &p_hmac) { + // Sanity check + if ((p_buffer == nullptr) || (p_secret_key == nullptr)) { + return -1; + } + ::HMAC_CTX_reset(_ctx); + + p_hmac = int2oct(0, EVP_MAX_MD_SIZE); + if (_hash_algorithms == hash_algorithms::sha_256) { + ::HMAC_Init_ex(_ctx, (const void *)p_secret_key, (long unsigned int)p_secret_key_length, EVP_sha256(), NULL); + } else if (_hash_algorithms == hash_algorithms::sha_384) { + ::HMAC_Init_ex(_ctx, (const void *)p_secret_key, (long unsigned int)p_secret_key_length, EVP_sha384(), NULL); + } else { // TODO To be continued + return -1; + } + // Compute the hash value + ::HMAC_Update(_ctx, p_buffer, p_buffer_length); + unsigned int length = p_hmac.lengthof(); + ::HMAC_Final(_ctx, (unsigned char *)static_cast(p_hmac), &length); + loggers::get_instance().log_to_hexa("hmac::generate: ", (unsigned char *)static_cast(p_hmac), length); + // Resize the hmac + if (_hash_algorithms == hash_algorithms::sha_256) { + p_hmac = OCTETSTRING(16, static_cast(p_hmac)); + } // FIXME Check length for the other hash algorithm + + return 0; +} diff --git a/ccsrc/security/src/security_externals.cc b/ccsrc/security/src/security_externals.cc new file mode 100644 index 0000000..96d5b8d --- /dev/null +++ b/ccsrc/security/src/security_externals.cc @@ -0,0 +1,82 @@ +#include "LibSecurity_Hash.hh" +#include "LibSecurity_Signature.hh" +#include "LibSecurity_Certificates.hh" + +#include "loggers.hh" + +#include "sha1.hh" +#include "sha256.hh" +#include "sha384.hh" +#include "certs_db.hh" +#include "security_services.hh" + +static std::unique_ptr _security_services; + +INTEGER LibSecurity__Certificates::fx__init__certs__db(const CHARSTRING& p_certs_db_path) { + loggers::get_instance().log_msg(">>> fx__init__certs__db: ", p_certs_db_path); + + int ret = _security_services->initialize(std::string(static_cast(p_certs_db_path))); + + loggers::get_instance().log("<<< fx__init__certs__db."); + return ret; +} + +INTEGER LibSecurity__Certificates::fx__load__certificate(const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name) { + loggers::get_instance().log_msg(">>> fx__load__certificate: ", p_certificate_name); + loggers::get_instance().log_msg(">>> fx__load__certificate: ", p_private_key_name); + + const X509* certificate; + int ret = _security_services->load_certificate(std::string(static_cast(p_certificate_name)), std::string(static_cast(p_private_key_name)), &certificate); + loggers::get_instance().log("fx__load__certificate: certificate: '%p'", certificate); + if (ret == 0) { + ASN1_INTEGER* asn1_serial = ::X509_get_serialNumber((X509*)certificate); + if (asn1_serial == nullptr) { + loggers::get_instance().log("fx__load__certificate: Failed to retrieve X509 serial number"); + return -1; + } + uint64_t v; + ASN1_INTEGER_get_uint64(&v, asn1_serial); + loggers::get_instance().log("fx__load__certificate: Loaded certificate: serial number: %ld", v); + } + + loggers::get_instance().log("<<< fx__load__certificate"); + return ret; +} + +OCTETSTRING LibSecurity__Hash::fx__hash(const OCTETSTRING& p_to_be_hashed, const LibSecurity__Hash::HashAlgorithm& p_hash_algorithm) { + loggers::get_instance().log_msg(">>> fx__hash: ", p_to_be_hashed); + + OCTETSTRING hash; + switch (p_hash_algorithm) { + case LibSecurity__Hash::HashAlgorithm::e__sha1: { + sha1 s; + s.generate(p_to_be_hashed, hash); + } + break; + case LibSecurity__Hash::HashAlgorithm::e__sha256: { + sha256 s; + s.generate(p_to_be_hashed, hash); + } + break; + case LibSecurity__Hash::HashAlgorithm::e__sha384: { + sha384 s; + s.generate(p_to_be_hashed, hash); + } + break; + } // End of 'switch' statement + + loggers::get_instance().log_msg("<<< fx__hash: ", hash); + return hash; +} + +INTEGER LibSecurity__Signature::fx__sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem) { + loggers::get_instance().log_msg(">>> fx__sign: ", p_encoded_message); + + if (_security_services->do_sign(p_encoded_message, p_certificate_name, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem) == -1) { + loggers::get_instance().log("fx__sign: Failed to signed message"); + return -1; + } + + return 0; +} + \ No newline at end of file diff --git a/ccsrc/security/src/securty_services.cc b/ccsrc/security/src/securty_services.cc new file mode 100644 index 0000000..455df75 --- /dev/null +++ b/ccsrc/security/src/securty_services.cc @@ -0,0 +1,122 @@ +#include +#include +#include + +#include "loggers.hh" + +#include "xml_converters.hh" + +#include "TTCN3.hh" + +#include "sha1.hh" +#include "sha256.hh" +#include "certs_loader.hh" +#include "security_services.hh" + +certs_db* security_services::_certs_db = nullptr; + +int security_services::initialize(const std::string& p_certs_db_path) { + loggers::get_instance().log(">>> security_services::initialize: '%s'", p_certs_db_path.c_str()); + + security_services::_certs_db = new certs_db(p_certs_db_path); + if (security_services::_certs_db == nullptr) { // Memory allocation issue + loggers::get_instance().warning("security_services::setup: _security_db pointer is NULL"); + return -1; + } + + loggers::get_instance().log("<<< security_services::initialize"); + return 0; +} + +int security_services::load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const X509** p_certificate) { + loggers::get_instance().log("security_services::load_certificate: '%s'", p_certificate_name.c_str()); + loggers::get_instance().log("security_services::load_certificate: '%s'", p_private_key_name.c_str()); + + return _certs_db->get_certificate(p_certificate_name, p_private_key_name, p_certificate); +} + +int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem) { + loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_encoded_message); + loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_certificate_name); + + // Canonicalization + std::string canonicalized; + xml_converters::get_instance().xml_canonicalization(std::string((const char*)(static_cast(p_encoded_message))), canonicalized); + OCTETSTRING encoded_message(char2oct(CHARSTRING(canonicalized.c_str()))); + loggers::get_instance().log("security_services::do_sign: canonicalized: '%s", canonicalized.c_str()); + + // Retrieve certificate + std::string certificate_id; + if (certs_loader::get_instance().get_certificate_id(std::string(static_cast(p_certificate_name)), certificate_id) != 0) { + loggers::get_instance().warning("fx__sign: Failed to retrieve certificate identifier"); + return -1; + } + loggers::get_instance().log("fx__sign: certificate_id: '%s'", certificate_id.c_str()); + const X509* certificate; + if (_certs_db->get_certificate(certificate_id, &certificate) != 0) { + loggers::get_instance().warning("fx__sign: Failed to retrieve certificate"); + return -1; + } + X509_NAME* sn = X509_get_subject_name((X509*)certificate); + std::string subject(512, (char)0x00); + X509_NAME_oneline(sn, (char*)subject.c_str(), subject.length()); + loggers::get_instance().log("fx__sign: certificate_id: X509_NAME_oneline: '%s'", subject.c_str()); + p_x509_certificate_subject = CHARSTRING(subject.c_str()); + X509_free((X509*)certificate); + + p_x509_certificate_pem = ""; // TODO + + // Compute the digest + sha256 digest; + digest.generate(char2oct(CHARSTRING(canonicalized.c_str())), p_digest); + loggers::get_instance().log_msg("fx__sign: certificate_id: p_digest: ", p_digest); + + // Retrive the private key + const EVP_PKEY* private_key; + int ret = _certs_db->get_private_key(certificate_id, &private_key); + if (ret == 1) { + loggers::get_instance().warning("fx__sign: Failed to retrieve private key"); + return -1; + } + loggers::get_instance().log("fx__sign: certificate_id: private_key: '%p'", private_key); + + // Create signing context + EVP_MD_CTX* ctx = ::EVP_MD_CTX_new(); + if (ctx == NULL) { + loggers::get_instance().warning("fx__sign: EVP_MD_CTX_create failed, error 0x%lx", ::ERR_get_error()); + return -1; + } + if (::EVP_DigestSignInit(ctx, NULL, EVP_sha256(), NULL, (EVP_PKEY*)private_key) != 1) { // FIXME Add parameter to chose the digest algorithm + loggers::get_instance().warning("fx__sign: EVP_DigestSignInit failed, error 0x%lx", ::ERR_get_error()); + ::EVP_MD_CTX_free(ctx); + return -1; + } + if (::EVP_DigestSignUpdate(ctx, (const unsigned char*)canonicalized.c_str(), canonicalized.length()) != 1) { + loggers::get_instance().warning("fx__sign: EVP_DigestSignUpdate failed, error 0x%lx", ::ERR_get_error()); + ::EVP_MD_CTX_free(ctx); + return -1; + } + // Get signature lengthof + size_t signature_length = 0; + if (::EVP_DigestSignFinal(ctx, NULL, &signature_length) != 1) { + loggers::get_instance().warning("fx__sign: EVP_DigestSignUpdate failed, error 0x%lx", ::ERR_get_error()); + ::EVP_MD_CTX_free(ctx); + return -1; + } + loggers::get_instance().log("fx__sign: signature_length: %d", signature_length); + std::vector s(signature_length, 0x00); + unsigned char* val = s.data(); + if (::EVP_DigestSignFinal(ctx, val, &signature_length) != 1) { + loggers::get_instance().warning("fx__sign: EVP_DigestSignUpdate failed, error 0x%lx", ::ERR_get_error()); + ::EVP_MD_CTX_free(ctx); + s.clear(); + return -1; + } + + p_signature = OCTETSTRING(signature_length, s.data()); + + ::EVP_MD_CTX_free(ctx); + loggers::get_instance().log_msg("fx__sign: signature: ", p_signature); + + return 0; +} \ No newline at end of file diff --git a/ccsrc/security/src/sha1.cc b/ccsrc/security/src/sha1.cc new file mode 100644 index 0000000..bd9386d --- /dev/null +++ b/ccsrc/security/src/sha1.cc @@ -0,0 +1,39 @@ +/*! + * \file sha1.cc + * \brief Source file for SHA-1 helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#include + +#include "sha1.hh" + +int sha1::generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash) { + // Sanity check + if (p_buffer.lengthof() == 0) { + p_hash = get_sha1_empty_string(); + return 0; + } + + return generate(static_cast(p_buffer), p_buffer.lengthof(), p_hash); +} + +int sha1::generate(const unsigned char* p_buffer, const size_t p_length, OCTETSTRING& p_hash) { + // Sanity check + if ((p_buffer == nullptr) || (p_length == 0)) { + p_hash = get_sha1_empty_string(); + return 0; + } + + // Resize data buffer + p_hash = int2oct(0, SHA_DIGEST_LENGTH); + // Compute the hash value + ::SHA1_Init(&_ctx); + ::SHA1_Update(&_ctx, p_buffer, p_length); + ::SHA1_Final((unsigned char*)static_cast(p_hash), &_ctx); + return 0; +}; diff --git a/ccsrc/security/src/sha256.cc b/ccsrc/security/src/sha256.cc new file mode 100644 index 0000000..e1fdf07 --- /dev/null +++ b/ccsrc/security/src/sha256.cc @@ -0,0 +1,39 @@ +/*! + * \file sha256.cc + * \brief Source file for SHA-256 helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#include + +#include "sha256.hh" + +int sha256::generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash) { + // Sanity check + if (p_buffer.lengthof() == 0) { + p_hash = get_sha256_empty_string(); + return 0; + } + + return generate(static_cast(p_buffer), p_buffer.lengthof(), p_hash); +} + +int sha256::generate(const unsigned char* p_buffer, const size_t p_length, OCTETSTRING& p_hash) { + // Sanity check + if ((p_buffer == nullptr) || (p_length == 0)) { + p_hash = get_sha256_empty_string(); + return 0; + } + + // Resize data buffer + p_hash = int2oct(0, SHA256_DIGEST_LENGTH); + // Compute the hash value + ::SHA256_Init(&_ctx); + ::SHA256_Update(&_ctx, p_buffer, p_length); + ::SHA256_Final((unsigned char*)static_cast(p_hash), &_ctx); + return 0; +}; diff --git a/ccsrc/security/src/sha384.cc b/ccsrc/security/src/sha384.cc new file mode 100644 index 0000000..9ad92fb --- /dev/null +++ b/ccsrc/security/src/sha384.cc @@ -0,0 +1,47 @@ +/*! + * \file sha384.cc + * \brief Sorce file for SHA-384 helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#include + +#include "sha384.hh" + +int sha384::generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash) { + // Sanity check + if (p_buffer.lengthof() == 0) { + p_hash = get_sha384_empty_string(); + return 0; + } + + return generate(static_cast(p_buffer), p_buffer.lengthof(), p_hash); +} + +int sha384::generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash) { + // Sanity check + if ((p_buffer == nullptr) || (p_length == 0)) { + p_hash = get_sha384_empty_string(); + return 0; + } + + // Resize data buffer + p_hash = int2oct(0, SHA384_DIGEST_LENGTH); + // Compute the hash value + ::SHA384_Init(&_ctx); + ::SHA384_Update(&_ctx, p_buffer, p_length); + ::SHA384_Final((unsigned char *)static_cast(p_hash), &_ctx); + return 0; +} + +const OCTETSTRING sha384::get_sha384_empty_string() const { + static unsigned char + sha384_empty_string[] = {0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, + 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, + 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b}; //! SHA-384 of an empty string + return OCTETSTRING(48, sha384_empty_string); +} diff --git a/ttcn/LibSecurity/module.mk b/ttcn/LibSecurity/module.mk new file mode 100644 index 0000000..4514de4 --- /dev/null +++ b/ttcn/LibSecurity/module.mk @@ -0,0 +1,5 @@ +sources := \ + ttcn/LibSecurity_Hash.ttcn \ + ttcn/LibSecurity_Hmac.ttcn \ + ttcn/LibSecurity_Signature.ttcn \ + ttcn/LibSecurity_Certificates.ttcn diff --git a/ttcn/LibSecurity/ttcn/LibSecurity_Certificates.ttcn b/ttcn/LibSecurity/ttcn/LibSecurity_Certificates.ttcn new file mode 100644 index 0000000..4fba516 --- /dev/null +++ b/ttcn/LibSecurity/ttcn/LibSecurity_Certificates.ttcn @@ -0,0 +1,15 @@ +module LibSecurity_Certificates { + + external function fx_init_certs_db(in charstring p_certs_db_path) return integer; + + external function fx_load_certificate(in charstring p_certificate_name, in charstring p_private_key_name) return integer; + + function f_init_certs_db(in charstring p_certs_db_path) return integer { + return fx_init_certs_db(p_certs_db_path); + } + + function f_load_certificate(in charstring p_certificate_name, in charstring p_private_key_name) return integer { + return fx_load_certificate(p_certificate_name, p_private_key_name); + } + +} // End of LibSecurity_Certificates \ No newline at end of file diff --git a/ttcn/LibSecurity/ttcn/LibSecurity_Hash.ttcn b/ttcn/LibSecurity/ttcn/LibSecurity_Hash.ttcn new file mode 100644 index 0000000..ecebd4f --- /dev/null +++ b/ttcn/LibSecurity/ttcn/LibSecurity_Hash.ttcn @@ -0,0 +1,21 @@ +module LibSecurity_Hash { + + type enumerated HashAlgorithm { + e_sha1, + e_sha256, + e_sha384 + } // End of type HashAlgorithm + + function f_hash( + in octetstring p_to_be_hased, + in HashAlgorithm p_hash_algorithm + ) return octetstring { + return fx_hash(p_to_be_hased, p_hash_algorithm); + } // End of function f_hash + + external function fx_hash( + in octetstring p_to_be_hased, + in HashAlgorithm p_hash_algorithm + ) return octetstring; + +} // End of module LibSecurity_Hash diff --git a/ttcn/LibSecurity/ttcn/LibSecurity_Hmac.ttcn b/ttcn/LibSecurity/ttcn/LibSecurity_Hmac.ttcn new file mode 100644 index 0000000..8f99e4e --- /dev/null +++ b/ttcn/LibSecurity/ttcn/LibSecurity_Hmac.ttcn @@ -0,0 +1,2 @@ +module LibSecurity_Hmac { +} // End of LibSecurity_Hmac \ No newline at end of file diff --git a/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn b/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn new file mode 100644 index 0000000..614caf6 --- /dev/null +++ b/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn @@ -0,0 +1,26 @@ +module LibSecurity_Signature { + + import from LibSecurity_Hash all; + + /** + * @desc + * @param [in] p_encoded_message The raw message to be signed + * @param [in] p_hash_algorithm The Hash algorithm to use + * @param [in] p_certificate_name The certificate to use for the signature + * @param [in] p_signature The raw signature + * @return 0 on success, -1 otherwise + */ + function f_sign( + in octetstring p_encoded_message, + in charstring p_certificate_name, + out octetstring p_signature, + out octetstring p_digest, + out charstring p_x509_certificate_subject, + out charstring p_x509_certificate_pem + ) return integer { + return fx_sign(p_encoded_message, p_certificate_name, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem); + } + + external function fx_sign(in octetstring p_encoded_message, in charstring p_certificate_name, out octetstring p_signature, out octetstring p_digest, out charstring p_x509_certificate_subject, out charstring p_x509_certificate_pem) return integer; + +} // End of LibSecurity_Signature \ No newline at end of file -- GitLab From b3e32ae45e559819ba3eab8ba748a03ff6fdd284 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Fri, 20 Jan 2023 10:07:15 +0100 Subject: [PATCH 09/37] Finalyze signature process --- ccsrc/Framework/include/codec_factory.hh | 2 +- .../Framework/include/codec_stack_builder.hh | 8 ++--- ccsrc/Framework/include/converter.hh | 18 +++++------ ccsrc/Framework/include/layer.hh | 4 +-- ccsrc/Framework/include/layer_factory.hh | 4 +-- .../Framework/include/layer_stack_builder.hh | 8 ++--- ccsrc/Framework/include/registration.hh | 8 ++--- ccsrc/Framework/include/t_layer.hh | 2 +- ccsrc/Framework/src/converter.cc | 10 +++--- ccsrc/Framework/src/layer_factory.cc | 4 +-- ccsrc/Protocols/ETH/ethernet_layer.cc | 2 +- ccsrc/Protocols/ETH/ethernet_layer.hh | 2 +- ccsrc/Protocols/ETH/ethernet_layer_factory.hh | 4 +-- ccsrc/Protocols/Http/http_codec.cc | 10 +++--- ccsrc/Protocols/Http/http_codec.hh | 24 +++++++------- ccsrc/Protocols/Http/http_layer.cc | 2 +- ccsrc/Protocols/Http/http_layer_factory.hh | 4 +-- ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc | 2 +- ccsrc/Protocols/Pcap/pcap_cygwin_layer.hh | 2 +- ccsrc/Protocols/Pcap/pcap_layer_factory.hh | 4 +-- ccsrc/Protocols/Pcap/pcap_linux_layer.cc | 2 +- ccsrc/Protocols/Pcap/pcap_linux_layer.hh | 2 +- ccsrc/Protocols/Pcap/pcap_offline_layer.cc | 6 ++-- ccsrc/Protocols/Pcap/pcap_offline_layer.hh | 2 +- .../Pcap/pcap_offline_layer_factory.hh | 4 +-- ccsrc/Protocols/Tcp/tcp_layer.cc | 4 +-- ccsrc/Protocols/Tcp/tcp_layer.hh | 4 +-- ccsrc/Protocols/Tcp/tcp_layer_factory.hh | 4 +-- ccsrc/Protocols/UDP/udp_layer.cc | 6 ++-- ccsrc/Protocols/UDP/udp_layer.hh | 6 ++-- ccsrc/Protocols/UDP/udp_layer_factory.hh | 4 +-- ccsrc/Protocols/Xml/src/xml_converters.cc | 2 +- ccsrc/loggers/loggers.hh | 8 ++--- ccsrc/security/include/certs_cache.hh | 16 ++++++---- ccsrc/security/include/certs_db.hh | 4 +-- ccsrc/security/include/certs_db_record.hh | 9 ++++-- ccsrc/security/include/certs_loader.hh | 2 +- ccsrc/security/include/security_services.hh | 2 +- ccsrc/security/src/certs_cache.cc | 27 ++++++++++++---- ccsrc/security/src/certs_db.cc | 4 +-- ccsrc/security/src/certs_db_record.cc | 9 +++--- ccsrc/security/src/certs_loader.cc | 32 ++++++++++++++++++- ccsrc/security/src/securty_services.cc | 9 ++++-- 43 files changed, 174 insertions(+), 118 deletions(-) diff --git a/ccsrc/Framework/include/codec_factory.hh b/ccsrc/Framework/include/codec_factory.hh index 9d09b73..ca93662 100644 --- a/ccsrc/Framework/include/codec_factory.hh +++ b/ccsrc/Framework/include/codec_factory.hh @@ -32,7 +32,7 @@ public: //! \publicsection */ codec_factory(){}; /*! - * \fn codec* create_codec(const std::string & type, const std::string & param); + * \fn codec* create_codec(const std::string& type, const std::string& param); * \brief Create the codecs stack based on the provided codecs stack description (cf. remark) * \param[in] p_type The provided codecs stack description * \param[in] p_params Optional parameters diff --git a/ccsrc/Framework/include/codec_stack_builder.hh b/ccsrc/Framework/include/codec_stack_builder.hh index ca1be9f..9e81d6b 100644 --- a/ccsrc/Framework/include/codec_stack_builder.hh +++ b/ccsrc/Framework/include/codec_stack_builder.hh @@ -38,24 +38,24 @@ public: //! \publicsection static codec_stack_builder *get_instance() { return _instance ? _instance : _instance = new codec_stack_builder(); }; /*! - * \fn void register_codec_factory(const std::string & p_type, codec_factory* p_codec_factory); + * \fn void register_codec_factory(const std::string& p_type, codec_factory* p_codec_factory); * \brief Add a new codec factory * \param[in] p_type The codec identifier (e.g. GN for the GeoNetworking codec...) * \param[in] p_codec_factory A reference to the \see codec_factory * \static */ - static void register_codec_factory(const std::string &p_type, codec_factory *p_codec_factory) { + static void register_codec_factory(const std::string& p_type, codec_factory *p_codec_factory) { codec_stack_builder::get_instance()->_register_codec_factory(p_type, p_codec_factory); }; private: //! \privatesection /*! - * \fn void _register_codec_factory(const std::string & p_type, codec_factory* p_codec_factory); + * \fn void _register_codec_factory(const std::string& p_type, codec_factory* p_codec_factory); * \brief Add a new codec factory * \param[in] p_type The codec identifier (e.g. GN for the GeoNetworking codec...) * \param[in] p_codec_factory A reference to the \see codec_factory */ - void _register_codec_factory(const std::string &p_type, codec_factory *p_codec_factory) { _codecs[p_type] = p_codec_factory; }; + void _register_codec_factory(const std::string& p_type, codec_factory *p_codec_factory) { _codecs[p_type] = p_codec_factory; }; public: //! \publicsection /*! diff --git a/ccsrc/Framework/include/converter.hh b/ccsrc/Framework/include/converter.hh index 6070f2d..844b43c 100644 --- a/ccsrc/Framework/include/converter.hh +++ b/ccsrc/Framework/include/converter.hh @@ -104,7 +104,7 @@ public: * \param[in] p_value The string value * \return The hexadecimal value */ - std::string string_to_hexa(const std::string &p_value, const bool p_uppercase = false); + std::string string_to_hexa(const std::string& p_value, const bool p_uppercase = false); /*! * \brief Convert a bytes array int32_t an hexadecimal string * \param[in] p_value The bytes array value @@ -116,7 +116,7 @@ public: * \param[in] p_value The hexadecimal value * \return The bytes array value */ - std::vector hexa_to_bytes(const std::string &p_value); + std::vector hexa_to_bytes(const std::string& p_value); /*! * \brief Convert a time in time_t format into a string formated according to RFC 822, 1036, 1123, 2822 @@ -279,7 +279,7 @@ public: * \param[in] p_value The string value * \return The bytes array value */ - inline std::vector string_to_bytes(const std::string &p_value) const { + inline std::vector string_to_bytes(const std::string& p_value) const { return std::vector(p_value.begin(), p_value.end()); }; // End of string_to_bytes @@ -298,7 +298,7 @@ public: * \param[in] p_value The string value * \return The integer value */ - inline int32_t string_to_int(const std::string &p_value) const { + inline int32_t string_to_int(const std::string& p_value) const { return std::stoi(p_value); // return atoi(p_value.c_str()); }; // End of string_to_int @@ -318,13 +318,13 @@ public: * \brief Convert a string in to lower case * \param[in/out] p_value The string value to convert */ - inline void to_lower(std::string &p_value) { std::transform(p_value.begin(), p_value.end(), p_value.begin(), ::tolower); } + inline void to_lower(std::string& p_value) { std::transform(p_value.begin(), p_value.end(), p_value.begin(), ::tolower); } /*! * \brief Convert a string in to upper case * \param[in/out] p_value The string value to convert */ - inline void to_upper(std::string &p_value) { std::transform(p_value.begin(), p_value.end(), p_value.begin(), ::toupper); } + inline void to_upper(std::string& p_value) { std::transform(p_value.begin(), p_value.end(), p_value.begin(), ::toupper); } public: /*! @@ -333,7 +333,7 @@ public: * \param[in] p_trim_chars The special characters to be omitted. Default: ' ' and TAB * \return The new string value */ - std::string trim(const std::string &p_value, const std::string &p_trim_chars = " \t"); + std::string trim(const std::string& p_value, const std::string& p_trim_chars = " \t"); /*! * \brief Convert the provided string into a list of arguments @@ -349,7 +349,7 @@ public: * } * \endcode */ - std::vector split(const std::string &p_value, const std::string &p_separator); + std::vector split(const std::string& p_value, const std::string& p_separator); /*! * \brief Convert the provided string into a list of arguments @@ -364,7 +364,7 @@ public: * } * \endcode */ - std::vector split_arguments_line(const std::string &p_value); + std::vector split_arguments_line(const std::string& p_value); /*! * \brief Convert the provided buffer into a Base64 diff --git a/ccsrc/Framework/include/layer.hh b/ccsrc/Framework/include/layer.hh index b42e68d..8a2183f 100644 --- a/ccsrc/Framework/include/layer.hh +++ b/ccsrc/Framework/include/layer.hh @@ -47,7 +47,7 @@ public: //! \publicsection * \remark This constructor is called by the layer factory * \see layer_factory */ - explicit layer(const std::string &p_type) : upperLayers(), lowerLayers(), type(std::string(p_type.begin(), p_type.end())){}; + explicit layer(const std::string& p_type) : upperLayers(), lowerLayers(), type(std::string(p_type.begin(), p_type.end())){}; /*! * \brief Default destructor @@ -117,7 +117,7 @@ public: //! \publicsection * \brief Remove the specified upper layer protocol from the list of the upper layer * \param[in] The layer protocol to be removed */ - inline const std::string &to_string() const { return type; }; + inline const std::string& to_string() const { return type; }; protected: //! \protectedsection inline void to_all_layers(std::vector &layers, OCTETSTRING &data, params ¶ms) { diff --git a/ccsrc/Framework/include/layer_factory.hh b/ccsrc/Framework/include/layer_factory.hh index 68e99c5..e3c1429 100644 --- a/ccsrc/Framework/include/layer_factory.hh +++ b/ccsrc/Framework/include/layer_factory.hh @@ -30,7 +30,7 @@ public: //! \publicsection */ layer_factory(){}; /*! - * \fn layer* create_layer(const std::string & type, const std::string & param); + * \fn layer* create_layer(const std::string& type, const std::string& param); * \brief Create the layers stack based on the provided layers stack description (cf. remark) * \param[in] p_type The provided layers stack description * \param[in] p_params Optional parameters @@ -59,5 +59,5 @@ public: //! \publicsection * save_mode : 1 to save sent packet, 0 otherwise * \pure */ - virtual layer *create_layer(const std::string &p_type, const std::string &p_params) = 0; + virtual layer *create_layer(const std::string& p_type, const std::string& p_params) = 0; }; // End of class layer_factory diff --git a/ccsrc/Framework/include/layer_stack_builder.hh b/ccsrc/Framework/include/layer_stack_builder.hh index 2d1b25a..83ad20b 100644 --- a/ccsrc/Framework/include/layer_stack_builder.hh +++ b/ccsrc/Framework/include/layer_stack_builder.hh @@ -38,22 +38,22 @@ public: //! \publicsection static layer_stack_builder *get_instance(); /*! - * \fn void register_layer_factory(const std::string & p_type, layer_factory* p_layer_factory); + * \fn void register_layer_factory(const std::string& p_type, layer_factory* p_layer_factory); * \brief Add a new layer factory * \param[in] p_type The layer identifier (e.g. GN for the GeoNetworking layer...) * \param[in] p_layer_factory A reference to the \see layer_factory * \static */ - static void register_layer_factory(const std::string &p_type, layer_factory *p_layer_factory); + static void register_layer_factory(const std::string& p_type, layer_factory *p_layer_factory); private: //! \privatesection /*! - * \fn void _register_layer_factory(const std::string & p_type, layer_factory* p_layer_factory); + * \fn void _register_layer_factory(const std::string& p_type, layer_factory* p_layer_factory); * \brief Add a new layer factory * \param[in] p_type The layer identifier (e.g. GN for the GeoNetworking layer...) * \param[in] p_layer_factory A reference to the \see layer_factory */ - void _register_layer_factory(const std::string &p_type, layer_factory *p_layer_factory); + void _register_layer_factory(const std::string& p_type, layer_factory *p_layer_factory); public: //! \publicsection /*! diff --git a/ccsrc/Framework/include/registration.hh b/ccsrc/Framework/include/registration.hh index df24ea1..0b2dbfe 100644 --- a/ccsrc/Framework/include/registration.hh +++ b/ccsrc/Framework/include/registration.hh @@ -35,8 +35,8 @@ public: }; public: - void add_item(const std::string &type, TItem *f); - TItem *get_item(const std::string &type); + void add_item(const std::string& type, TItem *f); + TItem *get_item(const std::string& type); }; // End of class registration template registration *registration::_instance = nullptr; @@ -46,9 +46,9 @@ template registration ®istration::get_instance return (_instance != nullptr) ? *_instance : *(_instance = new registration()); } -template void registration::add_item(const std::string &type, TItem *f) { _items[type] = f; } +template void registration::add_item(const std::string& type, TItem *f) { _items[type] = f; } -template TItem *registration::get_item(const std::string &type) { +template TItem *registration::get_item(const std::string& type) { typename std::map::const_iterator it = _items.find(type); if (it == _items.cend()) { return nullptr; diff --git a/ccsrc/Framework/include/t_layer.hh b/ccsrc/Framework/include/t_layer.hh index 286bd31..cbb5edf 100644 --- a/ccsrc/Framework/include/t_layer.hh +++ b/ccsrc/Framework/include/t_layer.hh @@ -39,7 +39,7 @@ public: //! \publicsection * \remark This constructor is called by the layer factory * \see layer_factory */ - explicit t_layer(const std::string &p_type) : layer(p_type), upperPorts(){}; + explicit t_layer(const std::string& p_type) : layer(p_type), upperPorts(){}; /*! * \inline * \fn void add_upper_port(TPort * p_port); diff --git a/ccsrc/Framework/src/converter.cc b/ccsrc/Framework/src/converter.cc index e9ad4d1..7a9a0cc 100644 --- a/ccsrc/Framework/src/converter.cc +++ b/ccsrc/Framework/src/converter.cc @@ -14,7 +14,7 @@ uint32_t converter::swap(const uint32_t p_value) { const std::string converter::lut_u = "0123456789ABCDEF"; const std::string converter::lut_l = "0123456789abcdef"; -std::string converter::string_to_hexa(const std::string &p_value, const bool p_uppercase) { +std::string converter::string_to_hexa(const std::string& p_value, const bool p_uppercase) { std::string input(p_value); std::for_each(input.begin(), input.end(), [](char &c) { c = std::toupper(c); }); @@ -68,7 +68,7 @@ inline uint8_t char2byte(const char p_ch) { return s; } -std::vector converter::hexa_to_bytes(const std::string &p_value) { +std::vector converter::hexa_to_bytes(const std::string& p_value) { // Sanity check std::vector output; size_t i = 0, idx = 0, outlen = (p_value.length() + 1) / 2; @@ -100,7 +100,7 @@ std::string converter::time_to_string(const struct tm &p_time) { return std::string(buffer); } -std::string converter::trim(const std::string &str, const std::string &whitespace) { +std::string converter::trim(const std::string& str, const std::string& whitespace) { size_t strBegin = str.find_first_not_of(whitespace); if (strBegin == std::string::npos) return ""; // no content @@ -111,7 +111,7 @@ std::string converter::trim(const std::string &str, const std::string &whitespac return str.substr(strBegin, strRange); } -std::vector converter::split(const std::string &p_value, const std::string &p_separator) { +std::vector converter::split(const std::string& p_value, const std::string& p_separator) { std::vector output; std::size_t current, previous = 0; current = p_value.find(p_separator); @@ -125,7 +125,7 @@ std::vector converter::split(const std::string &p_value, const std: return output; } -std::vector converter::split_arguments_line(const std::string &p_value) { +std::vector converter::split_arguments_line(const std::string& p_value) { std::vector output; std::string line = trim(p_value); if (!line.empty() && (line[0] == '-')) { // Valid command line diff --git a/ccsrc/Framework/src/layer_factory.cc b/ccsrc/Framework/src/layer_factory.cc index a28e2dc..e812ac7 100644 --- a/ccsrc/Framework/src/layer_factory.cc +++ b/ccsrc/Framework/src/layer_factory.cc @@ -10,14 +10,14 @@ layer_stack_builder *layer_stack_builder::_instance = NULL; // static functions layer_stack_builder *layer_stack_builder::get_instance() { return _instance ? _instance : _instance = new layer_stack_builder(); } -void layer_stack_builder::register_layer_factory(const std::string &p_type, layer_factory *p_layer_factory) { +void layer_stack_builder::register_layer_factory(const std::string& p_type, layer_factory *p_layer_factory) { layer_stack_builder::get_instance()->_register_layer_factory(p_type, p_layer_factory); } // member functions layer_stack_builder::layer_stack_builder() {} -void layer_stack_builder::_register_layer_factory(const std::string &p_type, layer_factory *p_layer_factory) { _layer_factories[p_type] = p_layer_factory; } +void layer_stack_builder::_register_layer_factory(const std::string& p_type, layer_factory *p_layer_factory) { _layer_factories[p_type] = p_layer_factory; } layer *layer_stack_builder::create_layer_stack(const char *p_layer_stack_description) { loggers::get_instance().log(">>> layer_stack_builder::create_layer_stack: '%s'", p_layer_stack_description); diff --git a/ccsrc/Protocols/ETH/ethernet_layer.cc b/ccsrc/Protocols/ETH/ethernet_layer.cc index 6405a96..0b6bff7 100644 --- a/ccsrc/Protocols/ETH/ethernet_layer.cc +++ b/ccsrc/Protocols/ETH/ethernet_layer.cc @@ -2,7 +2,7 @@ #include "loggers.hh" -ethernet_layer::ethernet_layer(const std::string & p_type, const std::string & p_param) : layer(p_type), _params() { +ethernet_layer::ethernet_layer(const std::string& p_type, const std::string& p_param) : layer(p_type), _params() { loggers::get_instance().log(">>> ethernet_layer::ethernet_layer: '%s', %s", to_string().c_str(), p_param.c_str()); // Setup parameters params::convert(_params, p_param); diff --git a/ccsrc/Protocols/ETH/ethernet_layer.hh b/ccsrc/Protocols/ETH/ethernet_layer.hh index f510350..57ae7c2 100644 --- a/ccsrc/Protocols/ETH/ethernet_layer.hh +++ b/ccsrc/Protocols/ETH/ethernet_layer.hh @@ -23,7 +23,7 @@ public: //! \publicsection * \param[in] p_type \todo * \param[in] p_param \todo */ - ethernet_layer(const std::string &p_type, const std::string &p_param); + ethernet_layer(const std::string& p_type, const std::string& p_param); /*! * \brief Default destructor */ diff --git a/ccsrc/Protocols/ETH/ethernet_layer_factory.hh b/ccsrc/Protocols/ETH/ethernet_layer_factory.hh index 7adf9f4..091b68d 100644 --- a/ccsrc/Protocols/ETH/ethernet_layer_factory.hh +++ b/ccsrc/Protocols/ETH/ethernet_layer_factory.hh @@ -31,12 +31,12 @@ public: //! \publicsection layer_stack_builder::register_layer_factory("ETH", this); }; /*! - * \fn layer* create_layer(const std::string & type, const std::string & param); + * \fn layer* create_layer(const std::string& type, const std::string& param); * \brief Create the layers stack based on the provided layers stack description * \param[in] p_type The provided layers stack description * \param[in] p_params Optional parameters * \return 0 on success, -1 otherwise * \inline */ - inline virtual layer *create_layer(const std::string &p_type, const std::string &p_param) { return new ethernet_layer(p_type, p_param); }; + inline virtual layer *create_layer(const std::string& p_type, const std::string& p_param) { return new ethernet_layer(p_type, p_param); }; }; // End of class ethernet_layer_factory diff --git a/ccsrc/Protocols/Http/http_codec.cc b/ccsrc/Protocols/Http/http_codec.cc index f0763bb..9240129 100644 --- a/ccsrc/Protocols/Http/http_codec.cc +++ b/ccsrc/Protocols/Http/http_codec.cc @@ -342,7 +342,7 @@ int http_codec::encode_response(const LibHttp__TypesAndValues::Response &p_respo return 0; } -int http_codec::decode_headers(TTCN_Buffer &decoding_buffer, LibHttp__TypesAndValues::Headers &headers, std::string &p_content_type) { +int http_codec::decode_headers(TTCN_Buffer &decoding_buffer, LibHttp__TypesAndValues::Headers &headers, std::string& p_content_type) { loggers::get_instance().log(">>> http_codec::decode_headers"); loggers::get_instance().log_to_hexa("http_codec::decode_headers: ", decoding_buffer); @@ -424,7 +424,7 @@ int http_codec::decode_header(CHARSTRING &header_line, LibHttp__TypesAndValues:: } int http_codec::encode_body(const LibHttp__MessageBodyTypes::HttpMessageBody &p_message_body, OCTETSTRING &p_encoding_buffer, - const std::string &p_content_type) { + const std::string& p_content_type) { loggers::get_instance().log_msg(">>> http_codec::encode_body: ", (const Base_Type &)p_message_body); // Sanity check @@ -469,7 +469,7 @@ int http_codec::encode_body(const LibHttp__MessageBodyTypes::HttpMessageBody &p_ return 0; } -int http_codec::decode_body(TTCN_Buffer &decoding_buffer, LibHttp__MessageBodyTypes::HttpMessageBody &message_body, const std::string &p_content_type) { +int http_codec::decode_body(TTCN_Buffer &decoding_buffer, LibHttp__MessageBodyTypes::HttpMessageBody &message_body, const std::string& p_content_type) { loggers::get_instance().log(">>> http_codec::decode_body"); loggers::get_instance().log_to_hexa("http_codec::decode_body", decoding_buffer); loggers::get_instance().log("http_codec::decode_body: # of codecs=%d - %p", _codecs.size(), this); @@ -641,7 +641,7 @@ int http_codec::get_line(TTCN_Buffer &buffer, CHARSTRING &to, const bool concate } // End of 'while' statement } -void http_codec::set_payload_codecs(const std::string &p_codecs) { +void http_codec::set_payload_codecs(const std::string& p_codecs) { loggers::get_instance().log(">>> http_codec::set_payload_codecs: '%s'", p_codecs.c_str()); // Sanity check @@ -678,7 +678,7 @@ void http_codec::set_payload_codecs(const std::string &p_codecs) { } } -bool http_codec::decode_body_html(const OCTETSTRING &p_data, CHARSTRING &p_html_body, const std::string &p_content_type, params* p_params) { +bool http_codec::decode_body_html(const OCTETSTRING &p_data, CHARSTRING &p_html_body, const std::string& p_content_type, params* p_params) { p_html_body = CHARSTRING(p_data.lengthof(), (char*)static_cast(p_data)); return true; } diff --git a/ccsrc/Protocols/Http/http_codec.hh b/ccsrc/Protocols/Http/http_codec.hh index efcebe2..04079e6 100644 --- a/ccsrc/Protocols/Http/http_codec.hh +++ b/ccsrc/Protocols/Http/http_codec.hh @@ -68,29 +68,29 @@ public: virtual int encode(const LibHttp__TypesAndValues::HttpMessage &, OCTETSTRING &data); virtual int decode(const OCTETSTRING &data, LibHttp__TypesAndValues::HttpMessage &, params *params = NULL); - void set_payload_codecs(const std::string &p_codecs); + void set_payload_codecs(const std::string& p_codecs); protected: //! \protectedsection - virtual bool encode_body_binary(const LibHttp__BinaryMessageBodyTypes::BinaryBody &p_binary_body, OCTETSTRING &p_encoding_buffer, const std::string &p_content_type) {return false;}; - virtual bool decode_body_binary(const OCTETSTRING &p_data, LibHttp__BinaryMessageBodyTypes::BinaryBody &p_binary_body, const std::string &p_content_type) {return false;}; + virtual bool encode_body_binary(const LibHttp__BinaryMessageBodyTypes::BinaryBody &p_binary_body, OCTETSTRING &p_encoding_buffer, const std::string& p_content_type) {return false;}; + virtual bool decode_body_binary(const OCTETSTRING &p_data, LibHttp__BinaryMessageBodyTypes::BinaryBody &p_binary_body, const std::string& p_content_type) {return false;}; - virtual bool encode_body_xml(const LibHttp__XmlMessageBodyTypes::XmlBody &p_xml_body, OCTETSTRING &p_encoding_buffer, const std::string &p_content_type) {return false;}; - virtual bool decode_body_xml(const OCTETSTRING &p_data, LibHttp__XmlMessageBodyTypes::XmlBody &p_body, const std::string &p_content_type, params* p_params) {return false;}; + virtual bool encode_body_xml(const LibHttp__XmlMessageBodyTypes::XmlBody &p_xml_body, OCTETSTRING &p_encoding_buffer, const std::string& p_content_type) {return false;}; + virtual bool decode_body_xml(const OCTETSTRING &p_data, LibHttp__XmlMessageBodyTypes::XmlBody &p_body, const std::string& p_content_type, params* p_params) {return false;}; - virtual bool encode_body_html(const CHARSTRING &p_html_body, OCTETSTRING &p_encoding_buffer, const std::string &p_content_type) {return false;}; - virtual bool decode_body_html(const OCTETSTRING &p_data, CHARSTRING &p_html_body, const std::string &p_content_type, params* p_params); + virtual bool encode_body_html(const CHARSTRING &p_html_body, OCTETSTRING &p_encoding_buffer, const std::string& p_content_type) {return false;}; + virtual bool decode_body_html(const OCTETSTRING &p_data, CHARSTRING &p_html_body, const std::string& p_content_type, params* p_params); - virtual bool encode_body_json(const LibHttp__JsonMessageBodyTypes::JsonBody &p_json_body, OCTETSTRING &p_encoding_buffer, const std::string &p_content_type) {return false;}; - virtual bool decode_body_json(const OCTETSTRING &p_data, LibHttp__JsonMessageBodyTypes::JsonBody &p_json_body, const std::string &p_content_type, params* p_params) {return false;}; + virtual bool encode_body_json(const LibHttp__JsonMessageBodyTypes::JsonBody &p_json_body, OCTETSTRING &p_encoding_buffer, const std::string& p_content_type) {return false;}; + virtual bool decode_body_json(const OCTETSTRING &p_data, LibHttp__JsonMessageBodyTypes::JsonBody &p_json_body, const std::string& p_content_type, params* p_params) {return false;}; private: int encode_request(const LibHttp__TypesAndValues::Request &p_request, TTCN_Buffer &p_encoding_buffer); int encode_response(const LibHttp__TypesAndValues::Response &p_response, TTCN_Buffer &p_encoding_buffer); - int encode_body(const LibHttp__MessageBodyTypes::HttpMessageBody &p_message_body, OCTETSTRING &p_encoding_buffer, const std::string &p_content_type); + int encode_body(const LibHttp__MessageBodyTypes::HttpMessageBody &p_message_body, OCTETSTRING &p_encoding_buffer, const std::string& p_content_type); - int decode_headers(TTCN_Buffer &decoding_buffer, LibHttp__TypesAndValues::Headers &headers, std::string &p_content_type); + int decode_headers(TTCN_Buffer &decoding_buffer, LibHttp__TypesAndValues::Headers &headers, std::string& p_content_type); int decode_header(CHARSTRING &header_line, LibHttp__TypesAndValues::Header &header); - int decode_body(TTCN_Buffer &decoding_buffer, LibHttp__MessageBodyTypes::HttpMessageBody &message_body, const std::string &p_content_type); + int decode_body(TTCN_Buffer &decoding_buffer, LibHttp__MessageBodyTypes::HttpMessageBody &message_body, const std::string& p_content_type); int get_line(TTCN_Buffer &buffer, CHARSTRING &to, const bool concatenate_header_lines = false); }; // End of class http_codec diff --git a/ccsrc/Protocols/Http/http_layer.cc b/ccsrc/Protocols/Http/http_layer.cc index 23f911c..bf4da9f 100644 --- a/ccsrc/Protocols/Http/http_layer.cc +++ b/ccsrc/Protocols/Http/http_layer.cc @@ -11,7 +11,7 @@ using namespace std; // Required for isnan() #include "LibHttp_TestSystem.hh" #include "LibHttp_TypesAndValues.hh" -http_layer::http_layer(const std::string &p_type, const std::string ¶m) +http_layer::http_layer(const std::string& p_type, const std::string& param) : t_layer(p_type), _params(), _codec(nullptr), _device_mode{false} { loggers::get_instance().log(">>> http_layer::http_layer: '%s', %s", to_string().c_str(), param.c_str()); // Setup parameters diff --git a/ccsrc/Protocols/Http/http_layer_factory.hh b/ccsrc/Protocols/Http/http_layer_factory.hh index 5e4e71a..5668e87 100644 --- a/ccsrc/Protocols/Http/http_layer_factory.hh +++ b/ccsrc/Protocols/Http/http_layer_factory.hh @@ -31,12 +31,12 @@ public: //! \publicsection layer_stack_builder::register_layer_factory("HTTP", this); }; /*! - * \fn layer* create_layer(const std::string & type, const std::string & param); + * \fn layer* create_layer(const std::string& type, const std::string& param); * \brief Create the layers stack based on the provided layers stack description * \param[in] p_type The provided layers stack description * \param[in] p_params Optional parameters * \return 0 on success, -1 otherwise * \inline */ - inline virtual layer *create_layer(const std::string &p_type, const std::string &p_param) { return new http_layer(p_type, p_param); }; + inline virtual layer *create_layer(const std::string& p_type, const std::string& p_param) { return new http_layer(p_type, p_param); }; }; // End of class http_layer_factory diff --git a/ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc b/ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc index f45d70e..dca0cfa 100644 --- a/ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc +++ b/ccsrc/Protocols/Pcap/pcap_cygwin_layer.cc @@ -52,7 +52,7 @@ static char * _bin2hex(char *hex, size_t hlen, const char *bin, size_t blen return hex + blen * 2; } -pcap_layer::pcap_layer(const std::string &p_type, const std::string ¶m) +pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _running(FALSE), _time_key("pcap_layer::Handle_Fd_Event_Readable") { loggers::get_instance().log(">>> pcap_layer::pcap_layer: '%s', %s", p_type.c_str(), param.c_str()); params::convert(_params, param); diff --git a/ccsrc/Protocols/Pcap/pcap_cygwin_layer.hh b/ccsrc/Protocols/Pcap/pcap_cygwin_layer.hh index d7d477a..b54ceda 100644 --- a/ccsrc/Protocols/Pcap/pcap_cygwin_layer.hh +++ b/ccsrc/Protocols/Pcap/pcap_cygwin_layer.hh @@ -52,7 +52,7 @@ public: //! \publicsection * \param[in] p_type \todo * \param[in] p_param \todo */ - pcap_layer(const std::string &p_type, const std::string ¶m); + pcap_layer(const std::string& p_type, const std::string& param); /*! * \brief Default destructor */ diff --git a/ccsrc/Protocols/Pcap/pcap_layer_factory.hh b/ccsrc/Protocols/Pcap/pcap_layer_factory.hh index 0125e19..79f2b6d 100644 --- a/ccsrc/Protocols/Pcap/pcap_layer_factory.hh +++ b/ccsrc/Protocols/Pcap/pcap_layer_factory.hh @@ -31,12 +31,12 @@ public: //! \publicsection layer_stack_builder::register_layer_factory("PCAP", this); }; /*! - * \fn layer* create_layer(const std::string & type, const std::string & param); + * \fn layer* create_layer(const std::string& type, const std::string& param); * \brief Create the layers stack based on the provided layers stack description * \param[in] p_type The provided layers stack description * \param[in] p_params Optional parameters * \return 0 on success, -1 otherwise * \inline */ - inline virtual layer *create_layer(const std::string &p_type, const std::string &p_param) { return new pcap_layer(p_type, p_param); }; + inline virtual layer *create_layer(const std::string& p_type, const std::string& p_param) { return new pcap_layer(p_type, p_param); }; }; // End of class pcap_layer_factory diff --git a/ccsrc/Protocols/Pcap/pcap_linux_layer.cc b/ccsrc/Protocols/Pcap/pcap_linux_layer.cc index ab9b5b8..27ce633 100644 --- a/ccsrc/Protocols/Pcap/pcap_linux_layer.cc +++ b/ccsrc/Protocols/Pcap/pcap_linux_layer.cc @@ -36,7 +36,7 @@ static char * _bin2hex(char *hex, size_t hlen, const char *bin, size_t blen return hex + blen * 2; } -pcap_layer::pcap_layer(const std::string &p_type, const std::string ¶m) +pcap_layer::pcap_layer(const std::string& p_type, const std::string& param) : layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _pcap_h(-1), _time_key("pcap_layer::Handle_Fd_Event_Readable") { char error_buffer[PCAP_ERRBUF_SIZE]; params::const_iterator it; diff --git a/ccsrc/Protocols/Pcap/pcap_linux_layer.hh b/ccsrc/Protocols/Pcap/pcap_linux_layer.hh index 82efc4b..90c45dd 100644 --- a/ccsrc/Protocols/Pcap/pcap_linux_layer.hh +++ b/ccsrc/Protocols/Pcap/pcap_linux_layer.hh @@ -35,7 +35,7 @@ public: //! \publicsection * \param[in] p_type \todo * \param[in] p_param \todo */ - pcap_layer(const std::string &p_type, const std::string ¶m); + pcap_layer(const std::string& p_type, const std::string& param); /*! * \brief Default destructor */ diff --git a/ccsrc/Protocols/Pcap/pcap_offline_layer.cc b/ccsrc/Protocols/Pcap/pcap_offline_layer.cc index b84cfc2..0f8808c 100644 --- a/ccsrc/Protocols/Pcap/pcap_offline_layer.cc +++ b/ccsrc/Protocols/Pcap/pcap_offline_layer.cc @@ -31,7 +31,7 @@ typedef struct pcap_pkthdr pcap_o_pkthdr; typedef struct timeval pcap_o_timeval; #endif -pcap_offline_layer::pcap_offline_layer(const std::string &p_type, const std::string ¶m) +pcap_offline_layer::pcap_offline_layer(const std::string& p_type, const std::string& param) : layer(p_type), PORT(p_type.c_str()), _params(), _device(NULL), _running(FALSE), _time_key("pcap_offline_layer::Handle_Fd_Event_Readable") { loggers::get_instance().log(">>> pcap_offline_layer::pcap_offline_layer: '%s', %s", p_type.c_str(), param.c_str()); params::convert(_params, param); @@ -49,14 +49,14 @@ pcap_offline_layer::pcap_offline_layer(const std::string &p_type, const std::str it = _params.find(std::string("file")); if ((it != _params.end()) && !it->second.empty()) { - const std::string &file = it->second; + const std::string& file = it->second; _device = pcap_open_offline(file.c_str(), error_buffer); if (_device) { // Add user defined filter it = _params.find(params::filter); if ((it != _params.end()) && !it->second.empty()) { - const std::string &filter = it->second; + const std::string& filter = it->second; // Log final PCAP filter loggers::get_instance().user("pcap_offline_layer::pcap_offline_layer: Filter: '%s'", filter.c_str()); struct bpf_program f = {0}; diff --git a/ccsrc/Protocols/Pcap/pcap_offline_layer.hh b/ccsrc/Protocols/Pcap/pcap_offline_layer.hh index 0c1993e..f4abd94 100644 --- a/ccsrc/Protocols/Pcap/pcap_offline_layer.hh +++ b/ccsrc/Protocols/Pcap/pcap_offline_layer.hh @@ -53,7 +53,7 @@ public: //! \publicsection * \param[in] p_type \todo * \param[in] p_param \todo */ - pcap_offline_layer(const std::string &p_type, const std::string ¶m); + pcap_offline_layer(const std::string& p_type, const std::string& param); /*! * \brief Default destructor */ diff --git a/ccsrc/Protocols/Pcap/pcap_offline_layer_factory.hh b/ccsrc/Protocols/Pcap/pcap_offline_layer_factory.hh index 23cd1d0..3c3d665 100644 --- a/ccsrc/Protocols/Pcap/pcap_offline_layer_factory.hh +++ b/ccsrc/Protocols/Pcap/pcap_offline_layer_factory.hh @@ -31,12 +31,12 @@ public: //! \publicsection layer_stack_builder::register_layer_factory("PCAP_FILE", this); }; /*! - * \fn layer* create_layer(const std::string & type, const std::string & param); + * \fn layer* create_layer(const std::string& type, const std::string& param); * \brief Create the layers stack based on the provided layers stack description * \param[in] p_type The provided layers stack description * \param[in] p_params Optional parameters * \return 0 on success, -1 otherwise * \inline */ - inline virtual layer *create_layer(const std::string &p_type, const std::string &p_param) { return new pcap_offline_layer(p_type, p_param); }; + inline virtual layer *create_layer(const std::string& p_type, const std::string& p_param) { return new pcap_offline_layer(p_type, p_param); }; }; // End of class pcap_offline_layer_factory diff --git a/ccsrc/Protocols/Tcp/tcp_layer.cc b/ccsrc/Protocols/Tcp/tcp_layer.cc index 945a148..c077355 100644 --- a/ccsrc/Protocols/Tcp/tcp_layer.cc +++ b/ccsrc/Protocols/Tcp/tcp_layer.cc @@ -8,7 +8,7 @@ #include "loggers.hh" -tcp_layer::tcp_layer(const std::string & p_type, const std::string & param) : layer(p_type), SSL_Socket(), PORT(p_type.c_str()), _params(), _client_id{-1}, _time_key("tcp_layer::Handle_Fd_Event_Readable"), _reconnect_on_send{false} { +tcp_layer::tcp_layer(const std::string& p_type, const std::string& param) : layer(p_type), SSL_Socket(), PORT(p_type.c_str()), _params(), _client_id{-1}, _time_key("tcp_layer::Handle_Fd_Event_Readable"), _reconnect_on_send{false} { loggers::get_instance().log(">>> tcp_layer::tcp_layer (1): '%s', %s", to_string().c_str(), param.c_str()); // Setup parameters params::convert(_params, param); @@ -16,7 +16,7 @@ tcp_layer::tcp_layer(const std::string & p_type, const std::string & param) : la init(); } -tcp_layer::tcp_layer(const std::string & p_type, const params & param) : layer(p_type), SSL_Socket(), PORT(p_type.c_str()), _params(), _client_id{-1}, _time_key("tcp_layer::Handle_Fd_Event_Readable"), _reconnect_on_send{false} { +tcp_layer::tcp_layer(const std::string& p_type, const params & param) : layer(p_type), SSL_Socket(), PORT(p_type.c_str()), _params(), _client_id{-1}, _time_key("tcp_layer::Handle_Fd_Event_Readable"), _reconnect_on_send{false} { loggers::get_instance().log(">>> tcp_layer::tcp_layer (2): '%s'", to_string().c_str()); // Setup parameters _params = param; diff --git a/ccsrc/Protocols/Tcp/tcp_layer.hh b/ccsrc/Protocols/Tcp/tcp_layer.hh index 3dbcba7..8db788c 100644 --- a/ccsrc/Protocols/Tcp/tcp_layer.hh +++ b/ccsrc/Protocols/Tcp/tcp_layer.hh @@ -35,14 +35,14 @@ public: //! \publicsection * \param[in] p_type \todo * \param[in] p_param \todo */ - tcp_layer(const std::string &p_type, const std::string &p_param); + tcp_layer(const std::string& p_type, const std::string& p_param); /*! * \brief Specialised constructor * Create a new instance of the tcp_layer class * \param[in] p_type \todo * \param[in] p_param \todo */ - tcp_layer(const std::string &p_type, const params &p_param); + tcp_layer(const std::string& p_type, const params &p_param); /*! * \brief Default destructor * \remark If \see _reconnect_on_send is set to false, the disconnection is done by the destructor diff --git a/ccsrc/Protocols/Tcp/tcp_layer_factory.hh b/ccsrc/Protocols/Tcp/tcp_layer_factory.hh index 4fe2009..017f3ec 100644 --- a/ccsrc/Protocols/Tcp/tcp_layer_factory.hh +++ b/ccsrc/Protocols/Tcp/tcp_layer_factory.hh @@ -31,11 +31,11 @@ public: //! \publicsection layer_stack_builder::register_layer_factory("TCP", this); }; /*! - * \fn layer* create_layer(const std::string & type, const std::string & param); + * \fn layer* create_layer(const std::string& type, const std::string& param); * \brief Create the layers stack based on the provided layers stack description * \param[in] p_type The provided layers stack description * \param[in] p_params Optional parameters * \return 0 on success, -1 otherwise */ - inline virtual layer *create_layer(const std::string &p_type, const std::string &p_param) { return new tcp_layer(p_type, p_param); }; + inline virtual layer *create_layer(const std::string& p_type, const std::string& p_param) { return new tcp_layer(p_type, p_param); }; }; // End of class tcp_layer_factory diff --git a/ccsrc/Protocols/UDP/udp_layer.cc b/ccsrc/Protocols/UDP/udp_layer.cc index b44d382..e17c530 100644 --- a/ccsrc/Protocols/UDP/udp_layer.cc +++ b/ccsrc/Protocols/UDP/udp_layer.cc @@ -11,7 +11,7 @@ #include #include -udp_layer::udp_layer(const std::string &p_type, const std::string ¶m) +udp_layer::udp_layer(const std::string& p_type, const std::string& param) : layer(p_type), PORT(p_type.c_str()), _params(), _saddr{0}, _daddr{0}, _reuse_incoming_source_adddress(false), _fd(-1), _time_key("udp_layer::Handle_Fd_Event_Readable") { loggers::get_instance().log(">>> udp_layer::udp_layer (1): '%s', %s, %p", to_string().c_str(), param.c_str(), (void*)this); @@ -22,7 +22,7 @@ udp_layer::udp_layer(const std::string &p_type, const std::string ¶m) init(); } -udp_layer::udp_layer(const std::string &p_type, const params ¶m) +udp_layer::udp_layer(const std::string& p_type, const params ¶m) : layer(p_type), PORT(p_type.c_str()), _params(), _saddr{0}, _daddr{0}, _reuse_incoming_source_adddress(false), _fd(-1), _time_key("udp_layer::Handle_Fd_Event_Readable") { loggers::get_instance().log(">>> udp_layer::udp_layer (2): '%s'", to_string().c_str()); @@ -162,7 +162,7 @@ void udp_layer::Handle_Fd_Event_Readable(int fd) { loggers::get_instance().set_stop_time(_time_key, duration); } -unsigned long udp_layer::get_host_id(const std::string &p_host_name) { +unsigned long udp_layer::get_host_id(const std::string& p_host_name) { loggers::get_instance().log(">>> udp_layer::get_host_id"); if (p_host_name.empty()) { diff --git a/ccsrc/Protocols/UDP/udp_layer.hh b/ccsrc/Protocols/UDP/udp_layer.hh index c24d833..4a212e8 100644 --- a/ccsrc/Protocols/UDP/udp_layer.hh +++ b/ccsrc/Protocols/UDP/udp_layer.hh @@ -43,14 +43,14 @@ public: //! \publicsection * \param[in] p_type \todo * \param[in] p_param \todo */ - udp_layer(const std::string &p_type, const std::string &p_param); + udp_layer(const std::string& p_type, const std::string& p_param); /*! * \brief Specialised constructor * Create a new instance of the udp_layer class * \param[in] p_type \todo * \param[in] p_param \todo */ - udp_layer(const std::string &p_type, const params &p_param); + udp_layer(const std::string& p_type, const params &p_param); /*! * \brief Default destructor */ @@ -79,6 +79,6 @@ protected: void init(); private: - unsigned long get_host_id(const std::string &p_host_name); + unsigned long get_host_id(const std::string& p_host_name); void close(); }; // End of class udp_layer diff --git a/ccsrc/Protocols/UDP/udp_layer_factory.hh b/ccsrc/Protocols/UDP/udp_layer_factory.hh index d08c503..2c6f7ab 100644 --- a/ccsrc/Protocols/UDP/udp_layer_factory.hh +++ b/ccsrc/Protocols/UDP/udp_layer_factory.hh @@ -31,12 +31,12 @@ public: //! \publicsection layer_stack_builder::register_layer_factory("UDP", this); }; /*! - * \fn layer* create_layer(const std::string & type, const std::string & param); + * \fn layer* create_layer(const std::string& type, const std::string& param); * \brief Create the layers stack based on the provided layers stack description * \param[in] p_type The provided layers stack description * \param[in] p_params Optional parameters * \return 0 on success, -1 otherwise * \inline */ - inline virtual layer *create_layer(const std::string &p_type, const std::string &p_param) { return new udp_layer(p_type, p_param); }; + inline virtual layer *create_layer(const std::string& p_type, const std::string& p_param) { return new udp_layer(p_type, p_param); }; }; // End of class udp_layer_factory diff --git a/ccsrc/Protocols/Xml/src/xml_converters.cc b/ccsrc/Protocols/Xml/src/xml_converters.cc index 014504d..aebace2 100644 --- a/ccsrc/Protocols/Xml/src/xml_converters.cc +++ b/ccsrc/Protocols/Xml/src/xml_converters.cc @@ -57,6 +57,6 @@ int xml_converters::xml_canonicalization(const std::string& p_to_canonical, std: } int xml_converters::xml_node_set_contains_callback(void* p_user_data, xmlNodePtr p_node, xmlNodePtr p_parent) { - loggers::get_instance().log("xml_converters::xml_node_set_contains_callback"); + //loggers::get_instance().log("xml_converters::xml_node_set_contains_callback"); return 1; } diff --git a/ccsrc/loggers/loggers.hh b/ccsrc/loggers/loggers.hh index 36f7344..035f2d1 100644 --- a/ccsrc/loggers/loggers.hh +++ b/ccsrc/loggers/loggers.hh @@ -157,7 +157,7 @@ public: //! \publicsection * \param[in] p_time_key A timer identifier (any string) * \inline */ - inline void set_start_time(std::string &p_time_key); + inline void set_start_time(std::string& p_time_key); /*! * \fn void set_stop_time(std::string& p_time_key, float& p_time); * \brief Stop execution time measurement @@ -165,7 +165,7 @@ public: //! \publicsection * \param[out] p_time The execution time measured in milliseconds * \inline */ - inline void set_stop_time(std::string &p_time_key, float &p_time); + inline void set_stop_time(std::string& p_time_key, float &p_time); }; // End of class loggers void loggers::log_to_hexa(const char *p_prompt, const TTCN_Buffer &buffer) { @@ -252,9 +252,9 @@ void loggers::error(const char *p_fmt, ...) { va_end(args); } -void loggers::set_start_time(std::string &p_time_key) { _times[p_time_key] = std::clock(); } +void loggers::set_start_time(std::string& p_time_key) { _times[p_time_key] = std::clock(); } -void loggers::set_stop_time(std::string &p_time_key, float &p_time) { +void loggers::set_stop_time(std::string& p_time_key, float &p_time) { std::map::iterator it = _times.find(p_time_key); if (it != loggers::_times.end()) { p_time = (std::clock() - _times[p_time_key]) * 1000.0 / CLOCKS_PER_SEC; // in milliseconds diff --git a/ccsrc/security/include/certs_cache.hh b/ccsrc/security/include/certs_cache.hh index e51f5e6..7d33e4f 100644 --- a/ccsrc/security/include/certs_cache.hh +++ b/ccsrc/security/include/certs_cache.hh @@ -52,21 +52,23 @@ public: /*! \publicsection */ */ int get_certificate(const std::string& p_certificate_id, const X509** p_certificate); /*! - * \fn int get_private_key(const std::string &p_certificate_id, const EVP_PKEY** p_private_key); + * \fn int get_private_key(const std::string& p_certificate_id, const EVP_PKEY** p_private_key); * \brief Retrive the private key of the specified certificate * \param[in] p_certificate_id The certificate name * \param[out] p_private_key The private key * \return 0 on success, -1 otherwise */ - int get_private_key(const std::string &p_certificate_id, const EVP_PKEY** p_private_key); + int get_private_key(const std::string& p_certificate_id, const EVP_PKEY** p_private_key); /*! - * \fn int get_public_keys(const std::string &p_certificate_id, const EVP_PKEY** p_public_key); + * \fn int get_public_keys(const std::string& p_certificate_id, const EVP_PKEY** p_public_key); * \brief Retrive the public keys (in uncompressed format) of the specified certificate * \param[in] p_certificate_id The certificate name * \param[out] p_public_key The public key * \return 0 on success, -1 otherwise */ - int get_public_keys(const std::string &p_certificate_id, const EVP_PKEY** p_public_key); + int get_public_keys(const std::string& p_certificate_id, const EVP_PKEY** p_public_key); + + int get_certificate_pem(const std::string& p_certificate_id, std::string& p_certificate_pem); virtual int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key); @@ -82,14 +84,14 @@ public: /*! \publicsection */ private: /*! \privatesection */ /*! - * \fn int load_certificate(const std::string &p_certificate_name, const std::string &p_private_key_name, const certs_db_record** p_record); + * \fn int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const certs_db_record** p_record); * \brief Retrive the specified certificate either from memory of from storage location * \param[in] p_certificate_name The certificate name * \param[in] p_private_key_name The certificate's private key name * \param[out] p_record A reference to the certificate record * \return 0 on success, -1 otherwise */ - int load_certificate(const std::string &p_certificate_name, const std::string &p_private_key_name, const certs_db_record** p_record); + int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const certs_db_record** p_record); /*! * \fn int load_certificate(const std::string& p_certificate_id, const certs_db_record** p_record); * \brief Retrive the specified certificate either from memory of from storage location @@ -97,6 +99,6 @@ private: /*! \privatesection */ * \param[out] p_record A reference to the certificate record * \return 0 on success, -1 otherwise */ - int load_certificate(const std::string &p_certificate_id, const certs_db_record** p_record); + int load_certificate(const std::string& p_certificate_id, const certs_db_record** p_record); }; // End of class certs_cache diff --git a/ccsrc/security/include/certs_db.hh b/ccsrc/security/include/certs_db.hh index 0f08fa4..adb4e14 100644 --- a/ccsrc/security/include/certs_db.hh +++ b/ccsrc/security/include/certs_db.hh @@ -24,7 +24,7 @@ public: /*! \publicsection */ * \brief Ctor with full path to the certificates storage * \param[in] p_db_path The full path to the certificates storage */ - certs_db(const std::string &p_db_path); + certs_db(const std::string& p_db_path); /*! * \brief Default dtor */ @@ -45,5 +45,5 @@ private: /*! \privatesection */ * \param[in] p_db_path The full path to the certificates storage * \return 0 on success, -1 otherwise */ - int initialize_cache(const std::string &p_db_path); + int initialize_cache(const std::string& p_db_path); }; // End of class certs_db diff --git a/ccsrc/security/include/certs_db_record.hh b/ccsrc/security/include/certs_db_record.hh index f98f82a..17de815 100644 --- a/ccsrc/security/include/certs_db_record.hh +++ b/ccsrc/security/include/certs_db_record.hh @@ -23,20 +23,22 @@ class certs_db_record { std::string _certificate_id; /*!< Certificate name */ X509* _certificate; /*!< X509 Certificate */ EVP_PKEY* _private_key; /*!< Private key */ + std::string _pem; /*!< Certificate PEM format */ public: /*! \publicsection */ /*! * \brief Default ctor */ explicit certs_db_record() - : _certificate_id(nullptr), _certificate(nullptr), _private_key(nullptr) {}; + : _certificate_id(nullptr), _certificate(nullptr), _private_key(nullptr), _pem{} {}; /*! * \brief Specialised ctor * \param[in] p_certificate_id The certificate identifier * \param[in] p_certificate The X509 certificate in openssl format * \param[in] p_private_key The certificate's private key in openssl format + * \param[in] p_certificate_pem The certificate's PEM format */ - certs_db_record(const std::string &p_certificate_id, X509* p_certificate, EVP_PKEY* p_private_key); + certs_db_record(const std::string& p_certificate_id, X509* p_certificate, EVP_PKEY* p_private_key, const std::string& p_certificate_pem); /*! * \brief Default dtor @@ -49,7 +51,7 @@ public: /*! \publicsection */ * \brief Retrieve the certificate identifier value * \return The certificate identifier */ - inline const std::string &certificate_id() const { return _certificate_id; }; + inline const std::string& certificate_id() const { return _certificate_id; }; /*! * \inline * \fn const X509* certificate() const; @@ -59,4 +61,5 @@ public: /*! \publicsection */ inline const X509* certificate() const { return _certificate; }; inline const EVP_PKEY* private_key() const { return _private_key; }; inline const EVP_PKEY* public_key() const { return ::X509_get_pubkey(_certificate); }; + inline const std::string& pem() const { return _pem; }; }; // End of class certs_db_record diff --git a/ccsrc/security/include/certs_loader.hh b/ccsrc/security/include/certs_loader.hh index 42fd162..3f408c6 100644 --- a/ccsrc/security/include/certs_loader.hh +++ b/ccsrc/security/include/certs_loader.hh @@ -62,7 +62,7 @@ public: /*! \publicsection */ }; /*! - * \fn int build_path(const std::string &p_root_directory); + * \fn int build_path(const std::string& p_root_directory); * \brief Set the pass of the certificate storage * \param[in] p_db_path The pass of the certificate storage */ diff --git a/ccsrc/security/include/security_services.hh b/ccsrc/security/include/security_services.hh index 99bfb5f..07b43ec 100644 --- a/ccsrc/security/include/security_services.hh +++ b/ccsrc/security/include/security_services.hh @@ -32,7 +32,7 @@ public: /*! \publicsection */ int initialize(const std::string& p_certs_db_path); int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const X509** p_certificate); /*! - * \fn int build_path(const std::string &p_root_directory); + * \fn int build_path(const std::string& p_root_directory); * \brief Set the pass of the certificate storage * \param[in] p_db_path The pass of the certificate storage */ diff --git a/ccsrc/security/src/certs_cache.cc b/ccsrc/security/src/certs_cache.cc index b0b413a..2aa7a5c 100644 --- a/ccsrc/security/src/certs_cache.cc +++ b/ccsrc/security/src/certs_cache.cc @@ -34,7 +34,7 @@ int certs_cache::clear() { return 0; } // End of clear method -int certs_cache::load_certificate(const std::string &p_certificate_id, const certs_db_record** p_record) { +int certs_cache::load_certificate(const std::string& p_certificate_id, const certs_db_record** p_record) { loggers::get_instance().log(">>> certs_cache::load_certificate (1): '%s'", p_certificate_id.c_str()); // Sanity check @@ -49,7 +49,7 @@ int certs_cache::load_certificate(const std::string &p_certificate_id, const cer return 0; } -int certs_cache::load_certificate(const std::string &p_certificate_name, const std::string &p_private_key_name, const certs_db_record** p_record) { +int certs_cache::load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const certs_db_record** p_record) { loggers::get_instance().log(">>> certs_cache::load_certificate (2): '%s'", p_certificate_name.c_str()); std::string certificate_id; @@ -77,7 +77,7 @@ int certs_cache::load_certificate(const std::string &p_certificate_name, const s return 0; } -int certs_cache::get_certificate(const std::string& p_certificate_name, const std::string &p_private_key_name, const X509** p_certificate) { +int certs_cache::get_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const X509** p_certificate) { loggers::get_instance().log(">>> certs_cache::get_certificate (1): '%s'", p_certificate_name.c_str()); const certs_db_record* record; @@ -92,7 +92,7 @@ int certs_cache::get_certificate(const std::string& p_certificate_name, const st return 0; } -int certs_cache::get_certificate(const std::string &p_certificate_id, const X509** p_certificate) { +int certs_cache::get_certificate(const std::string& p_certificate_id, const X509** p_certificate) { loggers::get_instance().log(">>> certs_cache::get_certificate (2): '%s'", p_certificate_id.c_str()); const certs_db_record* record; @@ -107,7 +107,7 @@ int certs_cache::get_certificate(const std::string &p_certificate_id, const X509 return 0; } -int certs_cache::get_private_key(const std::string &p_certificate_id, const EVP_PKEY** p_private_key) { +int certs_cache::get_private_key(const std::string& p_certificate_id, const EVP_PKEY** p_private_key) { loggers::get_instance().log(">>> certs_cache::get_private_key: '%s'", p_certificate_id.c_str()); const certs_db_record *record; @@ -122,7 +122,7 @@ int certs_cache::get_private_key(const std::string &p_certificate_id, const EVP_ return 0; } -int certs_cache::get_public_keys(const std::string &p_certificate_id, const EVP_PKEY** p_public_key) { +int certs_cache::get_public_keys(const std::string& p_certificate_id, const EVP_PKEY** p_public_key) { loggers::get_instance().log(">>> certs_cache::get_public_keys: '%s'", p_certificate_id.c_str()); const certs_db_record* record; @@ -137,6 +137,21 @@ int certs_cache::get_public_keys(const std::string &p_certificate_id, const EVP_ return 0; } +int certs_cache::get_certificate_pem(const std::string& p_certificate_id, std::string& p_certificate_pem) { + loggers::get_instance().log(">>> certs_cache::get_certificate_pem: '%s'", p_certificate_id.c_str()); + + const certs_db_record* record; + if (load_certificate(p_certificate_id, &record) == -1) { + loggers::get_instance().warning("certs_cache::get_certificate_pem: Failed to load certificate"); + return -1; + } + + p_certificate_pem = record->pem(); + loggers::get_instance().log("certs_cache::get_certificate_pem: p_certificate_pem: '%s'", p_certificate_pem); + + return 0; +} + int certs_cache::store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key) { loggers::get_instance().log(">>> certs_cache::store_certificate: '%s'", p_certificate_name.c_str()); diff --git a/ccsrc/security/src/certs_db.cc b/ccsrc/security/src/certs_db.cc index 0555519..b4cfc43 100644 --- a/ccsrc/security/src/certs_db.cc +++ b/ccsrc/security/src/certs_db.cc @@ -7,7 +7,7 @@ using namespace std; // Required for isnan() #include "certs_loader.hh" -certs_db::certs_db(const std::string &p_db_path) { +certs_db::certs_db(const std::string& p_db_path) { loggers::get_instance().log(">>> certs_db::certs_db: '%s'", p_db_path.c_str()); initialize_cache(p_db_path); @@ -16,7 +16,7 @@ certs_db::certs_db(const std::string &p_db_path) { certs_db::~certs_db() { loggers::get_instance().log(">>> certs_db::~certs_db"); } // End of dtor -int certs_db::initialize_cache(const std::string &p_db_path) { +int certs_db::initialize_cache(const std::string& p_db_path) { loggers::get_instance().log(">>> certs_db::initialize_cache: '%s'", p_db_path.c_str()); certs_loader::get_instance().build_path(p_db_path); diff --git a/ccsrc/security/src/certs_db_record.cc b/ccsrc/security/src/certs_db_record.cc index 59a0bd1..a5c34ba 100644 --- a/ccsrc/security/src/certs_db_record.cc +++ b/ccsrc/security/src/certs_db_record.cc @@ -15,10 +15,11 @@ #include "certs_db_record.hh" -certs_db_record::certs_db_record(const std::string &p_certificate_id, X509* p_certificate, EVP_PKEY* p_private_key) : _certificate_id(p_certificate_id), _certificate(p_certificate), _private_key(p_private_key) { - loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_certificate_id: '%s'", p_certificate_id.c_str()); - loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_certificate: '%p'", p_certificate); - loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_private_key: '%p'", p_private_key); +certs_db_record::certs_db_record(const std::string& p_certificate_id, X509* p_certificate, EVP_PKEY* p_private_key, const std::string& p_certificate_pem) : _certificate_id(p_certificate_id), _certificate(p_certificate), _private_key(p_private_key), _pem(p_certificate_pem) { + loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_certificate_id: '%s'", _certificate_id.c_str()); + loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_certificate: '%p'", _certificate_id); + loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_private_key: '%p'", _private_key); + loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_private_key: '%s'", _pem); } certs_db_record::~certs_db_record() { diff --git a/ccsrc/security/src/certs_loader.cc b/ccsrc/security/src/certs_loader.cc index dcb4b77..0fa3eb7 100644 --- a/ccsrc/security/src/certs_loader.cc +++ b/ccsrc/security/src/certs_loader.cc @@ -88,12 +88,41 @@ int certs_loader::load_certificate(const std::string& p_certificate_name, const } std::experimental::filesystem::path p = _db_path.string() + "/" + p_certificate_name; int ret = BIO_read_filename(certbio, p.string().c_str()); + X509* cert = ::PEM_read_bio_X509(certbio, NULL, 0, NULL); if (cert == nullptr) { loggers::get_instance().warning("certs_loader::load_certificate: Error loading cert into memory"); ::BIO_free_all(certbio); return -1; } + + std::unique_ptr bio(BIO_new(BIO_s_mem()), ::BIO_free); + ret = ::PEM_write_bio_X509(bio.get(), cert); + if (ret != 1) { + loggers::get_instance().warning("certs_loader::load_certificate: PEM_write_bio_X509 failed, error %s", ::ERR_get_error()); + ::X509_free(cert); + ::BIO_free_all(certbio); + return -1; + } + BUF_MEM *mem = NULL; + ::BIO_get_mem_ptr(bio.get(), &mem); + if (!mem || !mem->data || !mem->length) { + loggers::get_instance().warning("certs_loader::load_certificate: BIO_get_mem_ptr failed, error %s", ::ERR_get_error()); + ::X509_free(cert); + ::BIO_free_all(certbio); + return -1; + } + std::string pem(mem->data, mem->length); + // Remove labels + loggers::get_instance().log("certs_loader::load_certificate: certificate pem (1): '%s'", pem.c_str()); + std::string s("-----BEGIN CERTIFICATE-----\n"); + std::string::size_type idx = pem.find_first_of(s); + pem = pem.substr(s.length()); + s = "\n-----END CERTIFICATE-----\n"; + idx = pem.rfind(s); + pem = pem.substr(0, pem.length() - s.length()); + loggers::get_instance().log("certs_loader::load_certificate: certificate pem (2): '%s'", pem.c_str()); + ::BIO_free_all(certbio); // Load private key file @@ -123,9 +152,10 @@ int certs_loader::load_certificate(const std::string& p_certificate_name, const loggers::get_instance().log("certs_loader::load_certificate: p_certificate_id: '%s'", p_certificate_id.c_str()); loggers::get_instance().log("certs_loader::load_certificate: cert: '%p'", cert); loggers::get_instance().log("certs_loader::load_certificate: private_key: '%p'", private_key); + loggers::get_instance().log("certs_loader::load_certificate: certificate pem: '%s'", pem.c_str()); // Create new record - certs_db_record *r = new certs_db_record(p_certificate_name, cert, private_key); + certs_db_record *r = new certs_db_record(p_certificate_name, cert, private_key, pem); std::pair>::iterator, bool> result = p_certificates.insert(std::pair>(p_certificate_id, std::unique_ptr(r))); if (result.second == false) { loggers::get_instance().warning("certs_loader::build_certificates_cache: Failed to insert new record '%s'", p_certificate_name.c_str()); diff --git a/ccsrc/security/src/securty_services.cc b/ccsrc/security/src/securty_services.cc index 455df75..0103af5 100644 --- a/ccsrc/security/src/securty_services.cc +++ b/ccsrc/security/src/securty_services.cc @@ -41,7 +41,7 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARS // Canonicalization std::string canonicalized; - xml_converters::get_instance().xml_canonicalization(std::string((const char*)(static_cast(p_encoded_message))), canonicalized); + xml_converters::get_instance().xml_canonicalization(std::string((const char*)(static_cast(p_encoded_message)), p_encoded_message.lengthof()), canonicalized); OCTETSTRING encoded_message(char2oct(CHARSTRING(canonicalized.c_str()))); loggers::get_instance().log("security_services::do_sign: canonicalized: '%s", canonicalized.c_str()); @@ -64,7 +64,12 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARS p_x509_certificate_subject = CHARSTRING(subject.c_str()); X509_free((X509*)certificate); - p_x509_certificate_pem = ""; // TODO + std::string str; + if (_certs_db->get_certificate_pem(certificate_id, str) != 0) { + loggers::get_instance().warning("fx__sign: Failed to retrieve certificate PEM"); + return -1; + } + p_x509_certificate_pem = CHARSTRING(str.c_str()); // Compute the digest sha256 digest; -- GitLab From 923452dc20d27f7b3f81524d2161f5db7d57720a Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Tue, 14 Feb 2023 13:21:00 +0100 Subject: [PATCH 10/37] Enhance security support --- ccsrc/Framework/include/converter.hh | 6 +- ccsrc/Framework/src/converter.cc | 143 +++++++++++----- ccsrc/Protocols/Http/http_codec.cc | 4 +- ccsrc/Protocols/Tcp/tcp_layer.cc | 4 +- ccsrc/security/include/certs_cache.hh | 16 +- ccsrc/security/include/certs_db.hh | 8 - ccsrc/security/include/certs_db_record.hh | 1 + ccsrc/security/include/certs_loader.hh | 14 +- ccsrc/security/include/security_services.hh | 31 +++- ccsrc/security/src/certs_cache.cc | 66 ++++++-- ccsrc/security/src/certs_db.cc | 6 - ccsrc/security/src/certs_db_record.cc | 10 +- ccsrc/security/src/certs_loader.cc | 69 ++++++-- ccsrc/security/src/security_externals.cc | 19 ++- ccsrc/security/src/securty_services.cc | 152 +++++++++++++++--- .../ttcn/LibHttp_XmlMessageBodyTypes.ttcn | 8 +- .../ttcn/LibSecurity_Certificates.ttcn | 6 +- .../ttcn/LibSecurity_Signature.ttcn | 44 +++-- 18 files changed, 467 insertions(+), 140 deletions(-) diff --git a/ccsrc/Framework/include/converter.hh b/ccsrc/Framework/include/converter.hh index 844b43c..7f2adeb 100644 --- a/ccsrc/Framework/include/converter.hh +++ b/ccsrc/Framework/include/converter.hh @@ -371,17 +371,17 @@ public: * \param[in] p_value The buffer value * \return The Base64 encoded buffert */ - std::vector buffer_to_base64(const std::vector &p_value); + std::vector buffer_to_base64(const std::vector &p_value, const bool p_is_url = false); /*! * \brief Convert the provided Base64 buffer * \param[in] p_value The buffer value * \return The Base64 encoded buffert */ - std::vector base64_to_buffer(const std::vector &p_value); + std::vector base64_to_buffer(const std::vector &p_value, const bool p_remove_crlf = true); static const std::string lut_u; static const std::string lut_l; - static const std::string base64_enc_map; + static const std::string base64_enc_map[2]; }; // End of class converter diff --git a/ccsrc/Framework/src/converter.cc b/ccsrc/Framework/src/converter.cc index 7a9a0cc..0b2f376 100644 --- a/ccsrc/Framework/src/converter.cc +++ b/ccsrc/Framework/src/converter.cc @@ -1,5 +1,7 @@ #include "converter.hh" + #include + converter *converter::instance = NULL; uint16_t converter::swap(const uint16_t p_value) { @@ -40,22 +42,22 @@ std::string converter::string_to_hexa(const std::string& p_value, const bo } std::string converter::bytes_to_hexa(const std::vector &p_value, const bool p_uppercase) { - std::string ret; - ret.assign(p_value.size() * 2, ' '); + std::string out; + out.assign(p_value.size() * 2, ' '); if (p_uppercase) { // TODO Use pointer to reduce code size for (size_t i = 0; i < p_value.size(); i++) { uint8_t c = p_value[i]; - ret[i * 2] = lut_u[c >> 4]; - ret[i * 2 + 1] = lut_u[c & 0xF]; + out[i * 2] = lut_u[c >> 4]; + out[i * 2 + 1] = lut_u[c & 0xF]; } } else { for (size_t i = 0; i < p_value.size(); i++) { uint8_t c = p_value[i]; - ret[i * 2] = lut_l[c >> 4]; - ret[i * 2 + 1] = lut_l[c & 0xF]; + out[i * 2] = lut_l[c >> 4]; + out[i * 2 + 1] = lut_l[c & 0xF]; } } - return ret; + return out; } inline uint8_t char2byte(const char p_ch) { @@ -147,49 +149,112 @@ std::vector converter::split_arguments_line(const std::string& p_va return output; } -const std::string converter::base64_enc_map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +const std::string converter::base64_enc_map[2] = { + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + }; + +/** + * @brief Return the position of chr within base64_encode() + * @param[in] chr + * @return Return the position of chr within base64_encode() + */ +static unsigned char pos_of_char(const unsigned char chr) { + if ((chr >= 'A' && chr <= 'Z')) { + return static_cast(chr - 'A'); + } else if ((chr >= 'a' && chr <= 'z')) { + return static_cast(chr - 'a' + ('Z' - 'A') + 1); + } else if ((chr >= '0' && chr <= '9')) { + return static_cast(chr - '0' + ('Z' - 'A') + ('z' - 'a') + 2); + } else if ((chr == '+' || chr == '-')) { + return 62; // Be liberal with input and accept both url ('-') and non-url ('+') base 64 characters ( + } else if ((chr == '/' || chr == '_')) { + return 63; // Idem for '/' and '_' + } else { + throw std::runtime_error("Input is not valid base64-encoded data."); + } +} + +static std::string insert_linebreaks(std::string str, size_t distance) { + if (!str.length()) { + return ""; + } + size_t pos = distance; + while (pos < str.size()) { + str.insert(pos, "\n"); + pos += distance + 1; + } + return str; +} + +std::vector converter::buffer_to_base64(const std::vector &p_value, const bool p_is_url) { + const std::string& base64_enc_map_ = converter::base64_enc_map[(p_is_url) ? 1 : 0]; + const unsigned char trailing_char = (p_is_url) ? '.' : '='; -std::vector converter::buffer_to_base64(const std::vector &p_value) { std::vector out; + //out.resize((p_value.size() + 2) / 3 * 4); - int val = 0, valb = -6; - for (unsigned char c : p_value) { - val = (val << 8) + c; - valb += 8; - while (valb >= 0) { - out.push_back(converter::base64_enc_map[(val >> valb) & 0x3F]); - valb -= 6; + unsigned int pos = 0; + while (pos < p_value.size()) { + out.push_back(base64_enc_map_[(p_value[pos + 0] & 0xfc) >> 2]); + + if (pos+1 < p_value.size()) { + out.push_back(base64_enc_map_[((p_value[pos + 0] & 0x03) << 4) + ((p_value[pos + 1] & 0xf0) >> 4)]); + + if (pos+2 < p_value.size()) { + out.push_back(base64_enc_map_[((p_value[pos + 1] & 0x0f) << 2) + ((p_value[pos + 2] & 0xc0) >> 6)]); + out.push_back(base64_enc_map_[ p_value[pos + 2] & 0x3f]); + } else { + out.push_back(base64_enc_map_[(p_value[pos + 1] & 0x0f) << 2]); + out.push_back(trailing_char); + } + } else { + out.push_back(base64_enc_map_[(p_value[pos + 0] & 0x03) << 4]); + out.push_back(trailing_char); + out.push_back(trailing_char); + } + pos += 3; } // End of 'while' statement - } // End of 'for' statement - if (valb > -6) { - out.push_back(converter::base64_enc_map[((val << 8) >> (valb + 8)) & 0x3F]); - } - while (out.size() % 4) { - out.push_back('='); - } // End of 'while' statement return out; } -std::vector converter::base64_to_buffer(const std::vector &p_value) { - std::vector out; +std::vector converter::base64_to_buffer(const std::vector &p_value, const bool p_remove_crlf) { - std::vector T(256, -1); - for (int i = 0; i < 64; i++) { - T[converter::base64_enc_map[i]] = i; + if (p_value.size() == 0) { + return std::vector(); } - int val = 0, valb = -8; - for (unsigned char c : p_value) { - if (T[c] == -1) { - break; - } - val = (val << 6) + T[c]; - valb += 6; - if (valb >= 0) { - out.push_back((unsigned char)char((val >> valb) & 0xFF)); - valb -= 8; + std::vector value(p_value); + if (p_remove_crlf) { + value.erase(std::remove(value.begin(), value.end(), '\r'), value.end()); + value.erase(std::remove(value.begin(), value.end(), '\n'), value.end()); + } + + std::vector out; + //out.resize(value.size() / 4 * 3); + + size_t pos = 0; + while (pos < value.size()) { + size_t pos_of_char_1 = pos_of_char(value[pos + 1]); + out.push_back(((pos_of_char(value[pos])) << 2 ) + ( (pos_of_char_1 & 0x30 ) >> 4)); + + if ((pos + 2 < value.size()) && // Check for data that is not padded with equal signs (which is allowed by RFC 2045) + value[pos + 2] != '=' && + value[pos + 2] != '.' // accept URL-safe base 64 strings, too, so check for '.' also. + ) { + //Emit a chunk's second byte (which might not be produced in the last chunk). + unsigned int pos_of_char_2 = pos_of_char(value[pos + 2]); + out.push_back(((pos_of_char_1 & 0x0f) << 4) + ((pos_of_char_2 & 0x3c) >> 2)); + + if ((pos + 3 < value.size()) && value[pos + 3] != '=' && value[pos + 3] != '.' ) { + // Emit a chunk's third byte (which might not be produced in the last chunk). + out.push_back(((pos_of_char_2 & 0x03 ) << 6) + pos_of_char(value[pos + 3])); + } } - } // End of 'for' statement + + pos += 4; + } // End of 'while' statement + return out; } diff --git a/ccsrc/Protocols/Http/http_codec.cc b/ccsrc/Protocols/Http/http_codec.cc index 9240129..270c6c1 100644 --- a/ccsrc/Protocols/Http/http_codec.cc +++ b/ccsrc/Protocols/Http/http_codec.cc @@ -449,8 +449,8 @@ int http_codec::encode_body(const LibHttp__MessageBodyTypes::HttpMessageBody &p_ } } else if (p_message_body.ischosen(LibHttp__MessageBodyTypes::HttpMessageBody::ALT_xml__body)) { const LibHttp__XmlMessageBodyTypes::XmlBody &xml_body = p_message_body.xml__body(); - if (xml_body.ischosen(LibHttp__XmlMessageBodyTypes::XmlBody::ALT_raw)) { - p_encoding_buffer = OCTETSTRING(xml_body.raw().lengthof(), (unsigned char *)static_cast(xml_body.raw())); + if (xml_body.msg().ischosen(LibHttp__XmlMessageBodyTypes::XmlBodyMsg::ALT_raw)) { + p_encoding_buffer = OCTETSTRING(xml_body.msg().raw().lengthof(), (unsigned char *)static_cast(xml_body.msg().raw())); } else { encode_body_xml(xml_body, p_encoding_buffer, p_content_type); } diff --git a/ccsrc/Protocols/Tcp/tcp_layer.cc b/ccsrc/Protocols/Tcp/tcp_layer.cc index c077355..fdbeb35 100644 --- a/ccsrc/Protocols/Tcp/tcp_layer.cc +++ b/ccsrc/Protocols/Tcp/tcp_layer.cc @@ -37,6 +37,8 @@ void tcp_layer::init() { it = _params.find(std::string("tcp_fragmented")); if (it == _params.cend()) { _params.insert(std::pair(std::string("tcp_fragmented"), "0")); + } else { + _params.insert(std::pair(std::string("tcp_fragmented"), "1")); } bool server_mode = false; it = _params.find(params::server_mode); @@ -257,7 +259,7 @@ int tcp_layer::receive_message_on_fd(int p_client_id) loggers::get_instance().log("tcp_layer::receive_message_on_fd: Non secured mode"); if (_params[std::string("tcp_fragmented")].compare("1") == 0) { - sleep(5); // FIXME When HTTP paquet is fragmented into several TCP packets, a timer is required. This is a Q&D solution + sleep(4); // FIXME When HTTP paquet is fragmented into several TCP packets, a timer is required. This is a Q&D solution } return Abstract_Socket::receive_message_on_fd(p_client_id); } diff --git a/ccsrc/security/include/certs_cache.hh b/ccsrc/security/include/certs_cache.hh index 7d33e4f..70e24a3 100644 --- a/ccsrc/security/include/certs_cache.hh +++ b/ccsrc/security/include/certs_cache.hh @@ -30,6 +30,7 @@ class certs_cache { protected: /*! \protectedsection */ // TODO Enforce with const security_cache_record, and const std::string std::map _certificates_idx; //! List of the certificate names indexed by the certificate identifier, i.e. the SH1 of the certificate name + std::map _certificates_subject; //! List of the certificates indexed by the certificate subject name std::map> _certificates; //! List of the certificates indexed by the certificate identifier public: /*! \publicsection */ @@ -42,7 +43,7 @@ public: /*! \publicsection */ */ virtual ~certs_cache(); - int get_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const X509** p_certificate); + int get_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, const X509** p_certificate); /*! * \fn int get_certificate(const std::string& p_hashed_id8, const X509** p_certificate); * \brief Retrive the specified certificate either from memory @@ -51,7 +52,9 @@ public: /*! \publicsection */ * \return 0 on success, -1 otherwise */ int get_certificate(const std::string& p_certificate_id, const X509** p_certificate); - /*! + + int get_certificate_by_subject_name(const std::string& p_certificate_subject_name, const X509** p_certificate); +/*! * \fn int get_private_key(const std::string& p_certificate_id, const EVP_PKEY** p_private_key); * \brief Retrive the private key of the specified certificate * \param[in] p_certificate_id The certificate name @@ -70,7 +73,7 @@ public: /*! \publicsection */ int get_certificate_pem(const std::string& p_certificate_id, std::string& p_certificate_pem); - virtual int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key); + int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, std::string& p_certificate_id, const certs_db_record** p_record); /*! * \fn int int clear(); @@ -84,14 +87,15 @@ public: /*! \publicsection */ private: /*! \privatesection */ /*! - * \fn int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const certs_db_record** p_record); + * \fn int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, const certs_db_record** p_record); * \brief Retrive the specified certificate either from memory of from storage location * \param[in] p_certificate_name The certificate name - * \param[in] p_private_key_name The certificate's private key name + * \param[in] p_private_key_name The certificate's private key name, in PKCS#8 format + * \param[in] p_private_key_passwd The certificate's private key password for PKCS#8 format encryption. Empty if no encryption * \param[out] p_record A reference to the certificate record * \return 0 on success, -1 otherwise */ - int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const certs_db_record** p_record); + int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, const certs_db_record** p_record); /*! * \fn int load_certificate(const std::string& p_certificate_id, const certs_db_record** p_record); * \brief Retrive the specified certificate either from memory of from storage location diff --git a/ccsrc/security/include/certs_db.hh b/ccsrc/security/include/certs_db.hh index adb4e14..609ae4f 100644 --- a/ccsrc/security/include/certs_db.hh +++ b/ccsrc/security/include/certs_db.hh @@ -30,14 +30,6 @@ public: /*! \publicsection */ */ ~certs_db(); - /*! - * \fn int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key); - * \brief Store a new certificate - * \param[in] p_certificate_name The certificate name - * \return 0 on success, -1 otherwise - */ - int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key); - private: /*! \privatesection */ /*! * \fn int initialize_cache(const std::string& p_db_path); diff --git a/ccsrc/security/include/certs_db_record.hh b/ccsrc/security/include/certs_db_record.hh index 17de815..302b0f8 100644 --- a/ccsrc/security/include/certs_db_record.hh +++ b/ccsrc/security/include/certs_db_record.hh @@ -61,5 +61,6 @@ public: /*! \publicsection */ inline const X509* certificate() const { return _certificate; }; inline const EVP_PKEY* private_key() const { return _private_key; }; inline const EVP_PKEY* public_key() const { return ::X509_get_pubkey(_certificate); }; + inline const X509_NAME* subject_name() const { return ::X509_get_subject_name(_certificate); }; inline const std::string& pem() const { return _pem; }; }; // End of class certs_db_record diff --git a/ccsrc/security/include/certs_loader.hh b/ccsrc/security/include/certs_loader.hh index 3f408c6..ef7de83 100644 --- a/ccsrc/security/include/certs_loader.hh +++ b/ccsrc/security/include/certs_loader.hh @@ -76,22 +76,24 @@ public: /*! \publicsection */ */ int get_certificate_id(const std::string& p_certificate_name, std::string& p_certificate_id); /*! - * \fn int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, std::map> & p_certificates); + * \fn int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, std::map> & p_certificates); * \brief Store in memory the specified certificate * \param[in] p_certificate_name The certificate full path bame - * \param[in] p_private_key_name The certificate's private key full path name + * \param[in] p_private_key_name The certificate's private key full path name, in PKCS#8 format + * \param[in] p_private_key_passwd The certificate's private key password for PKCS#8 format encryption. Empty if no encryption * \param[out] p_certificate_id The certificate identifier * \param[inout] p_certificates The map of the loaded in memory certificates * \return 0 on success, -1 otherwise */ - int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, std::string& p_certificate_id, std::map> & p_certificates); + int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, std::string& p_certificate_id, std::map> & p_certificates); /*! - * \fn int save_certificate(const certs_db_record &p_certificate); + * \fn int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate_pem, std::string& p_certificate_id, std::map> & p_certificates); * \brief Save the specified certificate and update the internal maps - * \param[in] p_certificate The certificate to save + * \param[in] p_certificate_name The certificate neame + * \param[in] p_certificate_pem The certificate to save in PEM format * \param[out] p_certificate_id The certificate identifier * \return 0 on success, -1 otherwise */ - int save_certificate(const certs_db_record &p_certificate, std::string& p_certificate_id); + int store_certificate(const std::string& p_certificate_name, const std::string& p_certificate_pem, std::string& p_certificate_id, std::map> & p_certificates); }; // End of class certs_loader diff --git a/ccsrc/security/include/security_services.hh b/ccsrc/security/include/security_services.hh index 07b43ec..55befe0 100644 --- a/ccsrc/security/include/security_services.hh +++ b/ccsrc/security/include/security_services.hh @@ -30,11 +30,34 @@ public: /*! \publicsection */ }; int initialize(const std::string& p_certs_db_path); - int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const X509** p_certificate); + /*! + * \fn int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, std::map> & p_certificates); + * \brief Store in memory the specified certificate + * \param[in] p_certificate_name The certificate full path bame + * \param[in] p_private_key_name The certificate's private key full path name, in PKCS#8 format + * \param[in] p_private_key_passwd The certificate's private key password for PKCS#8 format encryption. Empty if no encryption + * \param[out] p_certificate_id The certificate identifier + * \param[inout] p_certificates The map of the loaded in memory certificates + * \return 0 on success, -1 otherwise + */ + int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, const X509** p_certificate); + /*! + * \fn int do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem); + * \brief Sign message + * \param[in] p_encoded_message The raw message to be signed + * \param[in] p_encoded_message The raw message to be signed + * \param[in] p_encoded_message The raw message to be signed + * \param[in] p_encoded_message The raw message to be signed + * \param[in] p_encoded_message The raw message to be signed + * \return 0 on success, -1 otherwise + */ + int do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_signed_canonicalized); /*! * \fn int build_path(const std::string& p_root_directory); - * \brief Set the pass of the certificate storage - * \param[in] p_db_path The pass of the certificate storage + * \brief Verify message signature + * \param[in] p_message The raw message to be verified + * \param[in] TODO + * \return true on success, false otherwise */ - int do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem); + bool do_sign_verify(const CHARSTRING& p_message, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate); }; \ No newline at end of file diff --git a/ccsrc/security/src/certs_cache.cc b/ccsrc/security/src/certs_cache.cc index 2aa7a5c..c41d7b0 100644 --- a/ccsrc/security/src/certs_cache.cc +++ b/ccsrc/security/src/certs_cache.cc @@ -19,7 +19,7 @@ #include "loggers.hh" -certs_cache::certs_cache() : _certificates_idx(), _certificates() { loggers::get_instance().log(">>> certs_cache::certs_cache"); } // End of ctor +certs_cache::certs_cache() : _certificates_idx(), _certificates_subject(), _certificates() { loggers::get_instance().log(">>> certs_cache::certs_cache"); } // End of ctor certs_cache::~certs_cache() { loggers::get_instance().log(">>> certs_cache::~certs_cache"); @@ -30,6 +30,7 @@ int certs_cache::clear() { loggers::get_instance().log(">>> certs_cache::clear"); _certificates.clear(); // Smart pointers will do the job _certificates_idx.clear(); + _certificates_subject.clear(); return 0; } // End of clear method @@ -49,7 +50,7 @@ int certs_cache::load_certificate(const std::string& p_certificate_id, const cer return 0; } -int certs_cache::load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const certs_db_record** p_record) { +int certs_cache::load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, const certs_db_record** p_record) { loggers::get_instance().log(">>> certs_cache::load_certificate (2): '%s'", p_certificate_name.c_str()); std::string certificate_id; @@ -62,26 +63,34 @@ int certs_cache::load_certificate(const std::string& p_certificate_name, const s std::map::const_iterator s = _certificates_idx.find(certificate_id); if (s == _certificates_idx.cend()) { // Certificate is not in the DB loggers::get_instance().log("certs_cache::load_certificate (2): Record not found"); - if (certs_loader::get_instance().load_certificate(p_certificate_name, p_private_key_name, certificate_id, _certificates) == -1) { + if (certs_loader::get_instance().load_certificate(p_certificate_name, p_private_key_name, p_private_key_passwd, certificate_id, _certificates) == -1) { loggers::get_instance().warning("certs_cache::load_certificate: Failed to load certificate"); return -1; } + // Certificate is on the DB, load it + std::map>::const_iterator it = _certificates.find(certificate_id); + *p_record = it->second.get(); // Mapping certificate id/certificate name _certificates_idx.insert(std::pair(certificate_id, p_certificate_name)); + std::string sn(512, (char)0x00); + const X509_NAME* subject = (*p_record)->subject_name(); + ::X509_NAME_oneline(subject, sn.data(), sn.length()); + loggers::get_instance().log("certs_cache::load_certificate: sn: '%s'", sn.c_str()); + _certificates_subject.insert(std::pair(sn, certificate_id)); + } else { + // Certificate is on the DB, load it + std::map>::const_iterator it = _certificates.find(certificate_id); + *p_record = it->second.get(); } - // Certificate is on the DB, load it if required - std::map>::const_iterator it = _certificates.find(certificate_id); - *p_record = it->second.get(); - return 0; } -int certs_cache::get_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const X509** p_certificate) { +int certs_cache::get_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, const X509** p_certificate) { loggers::get_instance().log(">>> certs_cache::get_certificate (1): '%s'", p_certificate_name.c_str()); const certs_db_record* record; - if (load_certificate(p_certificate_name, p_private_key_name, &record) == -1) { + if (load_certificate(p_certificate_name, p_private_key_name, p_private_key_passwd, &record) == -1) { loggers::get_instance().warning("certs_cache::get_certificate (1): Failed to load certificate"); return -1; } @@ -107,6 +116,24 @@ int certs_cache::get_certificate(const std::string& p_certificate_id, const X509 return 0; } +int certs_cache::get_certificate_by_subject_name(const std::string& p_certificate_subject_name, const X509** p_certificate) { + loggers::get_instance().log(">>> certs_cache::get_certificate_by_subject_name: '%s'", p_certificate_subject_name.c_str()); + + std::map::const_iterator s = _certificates_subject.find(p_certificate_subject_name); + if (s == _certificates_subject.cend()) { // Certificate is not in the DB + loggers::get_instance().warning("certs_cache::get_certificate_by_subject_name: Record not found"); + return -1; + } + + if (get_certificate(s->second, p_certificate) == -1) { + loggers::get_instance().error("certs_cache::get_certificate_by_subject_name: DB corrupted: '%s'", s->second.c_str()); + return -1; + } + loggers::get_instance().log("certs_cache::get_certificate_by_subject_name: p_certificate: '%p'", *p_certificate); + + return 0; +} + int certs_cache::get_private_key(const std::string& p_certificate_id, const EVP_PKEY** p_private_key) { loggers::get_instance().log(">>> certs_cache::get_private_key: '%s'", p_certificate_id.c_str()); @@ -147,15 +174,30 @@ int certs_cache::get_certificate_pem(const std::string& p_certificate_id, std::s } p_certificate_pem = record->pem(); - loggers::get_instance().log("certs_cache::get_certificate_pem: p_certificate_pem: '%s'", p_certificate_pem); + loggers::get_instance().log("certs_cache::get_certificate_pem: p_certificate_pem: '%s'", p_certificate_pem.c_str()); return 0; } -int certs_cache::store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key) { +int certs_cache::store_certificate(const std::string& p_certificate_name, const std::string& p_certificate_pem, std::string& p_certificate_id, const certs_db_record** p_record) { loggers::get_instance().log(">>> certs_cache::store_certificate: '%s'", p_certificate_name.c_str()); - return -1; + if (certs_loader::get_instance().store_certificate(p_certificate_name, p_certificate_pem, p_certificate_id, _certificates) == -1) { + loggers::get_instance().warning("certs_cache::store_certificate: Failed to load certificate"); + return -1; + } + // Certificate is on the DB, load it + std::map>::const_iterator it = _certificates.find(p_certificate_id); + *p_record = it->second.get(); + // Mapping certificate id/certificate name + _certificates_idx.insert(std::pair(p_certificate_id, p_certificate_name)); + std::string sn(512, (char)0x00); + const X509_NAME* subject = (*p_record)->subject_name(); + ::X509_NAME_oneline(subject, sn.data(), sn.length()); + loggers::get_instance().log("certs_cache::store_certificate: sn: '%s'", sn.c_str()); + _certificates_subject.insert(std::pair(sn, p_certificate_id)); + + return 0; } void certs_cache::dump() const { diff --git a/ccsrc/security/src/certs_db.cc b/ccsrc/security/src/certs_db.cc index b4cfc43..4bc3193 100644 --- a/ccsrc/security/src/certs_db.cc +++ b/ccsrc/security/src/certs_db.cc @@ -24,9 +24,3 @@ int certs_db::initialize_cache(const std::string& p_db_path) { loggers::get_instance().log("<<< certs_db::initialize_cache"); return 0; } - -int certs_db::store_certificate(const std::string& p_certificate_name, const std::string& p_certificate, const EVP_PKEY* p_private_key) { - loggers::get_instance().log(">>> certs_db::store_certificate: '%s'", p_certificate_name.c_str()); - - return -1; -} diff --git a/ccsrc/security/src/certs_db_record.cc b/ccsrc/security/src/certs_db_record.cc index a5c34ba..2439e4a 100644 --- a/ccsrc/security/src/certs_db_record.cc +++ b/ccsrc/security/src/certs_db_record.cc @@ -17,14 +17,16 @@ certs_db_record::certs_db_record(const std::string& p_certificate_id, X509* p_certificate, EVP_PKEY* p_private_key, const std::string& p_certificate_pem) : _certificate_id(p_certificate_id), _certificate(p_certificate), _private_key(p_private_key), _pem(p_certificate_pem) { loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_certificate_id: '%s'", _certificate_id.c_str()); - loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_certificate: '%p'", _certificate_id); - loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_private_key: '%p'", _private_key); - loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_private_key: '%s'", _pem); + // loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_certificate: '%p'", _certificate_id); + // loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_private_key: '%p'", _private_key); + //loggers::get_instance().log(">>> certs_db_record::certs_db_record: p_private_key: '%s'", _pem.c_str()); } certs_db_record::~certs_db_record() { if (_certificate != nullptr) { ::X509_free(_certificate); - ::EVP_PKEY_free(_private_key); + if (_private_key != nullptr) { + ::EVP_PKEY_free(_private_key); + } } } diff --git a/ccsrc/security/src/certs_loader.cc b/ccsrc/security/src/certs_loader.cc index 0fa3eb7..ec98eae 100644 --- a/ccsrc/security/src/certs_loader.cc +++ b/ccsrc/security/src/certs_loader.cc @@ -76,8 +76,8 @@ int certs_loader::get_certificate_id(const std::string& p_certificate_name, std: return 0; } -int certs_loader::load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, std::string& p_certificate_id, std::map> & p_certificates) { - loggers::get_instance().log(">>> certs_loader::load_certificate %s", p_certificate_name.c_str()); +int certs_loader::load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, std::string& p_certificate_id, std::map> & p_certificates) { + loggers::get_instance().log(">>> certs_loader::load_certificate '%s'", p_certificate_name.c_str()); loggers::get_instance().log(">>> certs_loader::load_certificate: '%s'", p_private_key_name.c_str()); // Load certificate file @@ -87,6 +87,7 @@ int certs_loader::load_certificate(const std::string& p_certificate_name, const return -1; } std::experimental::filesystem::path p = _db_path.string() + "/" + p_certificate_name; + loggers::get_instance().log("certs_loader::load_certificate: p='%s'", p.string().c_str()); int ret = BIO_read_filename(certbio, p.string().c_str()); X509* cert = ::PEM_read_bio_X509(certbio, NULL, 0, NULL); @@ -114,14 +115,14 @@ int certs_loader::load_certificate(const std::string& p_certificate_name, const } std::string pem(mem->data, mem->length); // Remove labels - loggers::get_instance().log("certs_loader::load_certificate: certificate pem (1): '%s'", pem.c_str()); + //loggers::get_instance().log("certs_loader::load_certificate: certificate pem (1): '%s'", pem.c_str()); std::string s("-----BEGIN CERTIFICATE-----\n"); std::string::size_type idx = pem.find_first_of(s); pem = pem.substr(s.length()); s = "\n-----END CERTIFICATE-----\n"; idx = pem.rfind(s); pem = pem.substr(0, pem.length() - s.length()); - loggers::get_instance().log("certs_loader::load_certificate: certificate pem (2): '%s'", pem.c_str()); + //loggers::get_instance().log("certs_loader::load_certificate: certificate pem (2): '%s'", pem.c_str()); ::BIO_free_all(certbio); @@ -134,7 +135,11 @@ int certs_loader::load_certificate(const std::string& p_certificate_name, const } p = _db_path.string() + "/" + p_private_key_name; ret = BIO_read_filename(certbio, p.string().c_str()); - EVP_PKEY* private_key = ::PEM_read_bio_PrivateKey(certbio, NULL, 0, NULL); + pem_password_cb* cb = NULL; + if (!p_private_key_passwd.empty() > 0) { + // TODO + } + EVP_PKEY* private_key = ::PEM_read_bio_PrivateKey(certbio, NULL, cb, NULL); if (private_key == nullptr) { loggers::get_instance().warning("certs_loader::load_certificate: Error loading cert into memory"); ::X509_free(cert); @@ -152,7 +157,7 @@ int certs_loader::load_certificate(const std::string& p_certificate_name, const loggers::get_instance().log("certs_loader::load_certificate: p_certificate_id: '%s'", p_certificate_id.c_str()); loggers::get_instance().log("certs_loader::load_certificate: cert: '%p'", cert); loggers::get_instance().log("certs_loader::load_certificate: private_key: '%p'", private_key); - loggers::get_instance().log("certs_loader::load_certificate: certificate pem: '%s'", pem.c_str()); + //loggers::get_instance().log("certs_loader::load_certificate: certificate pem: '%s'", pem.c_str()); // Create new record certs_db_record *r = new certs_db_record(p_certificate_name, cert, private_key, pem); @@ -166,8 +171,54 @@ int certs_loader::load_certificate(const std::string& p_certificate_name, const return 0; } -int certs_loader::save_certificate(const certs_db_record &p_certificate, std::string& p_certificate_id) { +int certs_loader::store_certificate(const std::string& p_certificate_name, const std::string& p_certificate_pem, std::string& p_certificate_id, std::map> & p_certificates) { + loggers::get_instance().log(">>> certs_loader::store_certificate '%s'", p_certificate_name.c_str()); + loggers::get_instance().log(">>> certs_loader::store_certificate: '%s'", p_certificate_pem.c_str()); + + // Build the certificate identifier + if (get_certificate_id(p_certificate_name, p_certificate_id) != 0) { + loggers::get_instance().warning("certs_cache::store_certificate: Failed to build the certificate identifier"); + return -1; + } - return -1; -} // End of method save_certificate + // Load certificate file + std::string s("-----BEGIN CERTIFICATE-----\n"); + if (p_certificate_pem.find(s) == std::string::npos) { // Add delimeters + loggers::get_instance().log("certs_loader::store_certificate: Add delimeters"); + s = s.append(p_certificate_pem); + s = s.append("\n-----END CERTIFICATE-----\n"); + } else { + loggers::get_instance().log("certs_loader::store_certificate: Do not add delimeters"); + s = p_certificate_pem; + } + loggers::get_instance().log("certs_loader::store_certificate: pem: '%s'", s.c_str()); + BIO* certbio = ::BIO_new_mem_buf(s.c_str(), -1); + if (certbio == nullptr) { + loggers::get_instance().warning("certs_loader::store_certificate: Error creating in memory BIO"); + return -1; + } + + X509* cert = ::PEM_read_bio_X509(certbio, NULL, 0, NULL); + if (cert == nullptr) { + loggers::get_instance().warning("certs_loader::store_certificate: Error loading cert into memory"); + ::BIO_free_all(certbio); + return -1; + } + ::BIO_free(certbio); + + loggers::get_instance().log("certs_loader::store_certificate: p_certificate_name: '%s'", p_certificate_name.c_str()); + loggers::get_instance().log("certs_loader::store_certificate: p_certificate_id: '%s'", p_certificate_id.c_str()); + loggers::get_instance().log("certs_loader::store_certificate: cert: '%p'", cert); + + // Create new record + certs_db_record *r = new certs_db_record(p_certificate_name, cert, nullptr, p_certificate_pem); + std::pair>::iterator, bool> result = p_certificates.insert(std::pair>(p_certificate_id, std::unique_ptr(r))); + if (result.second == false) { + loggers::get_instance().warning("certs_loader::store_certificate: Failed to insert new record '%s'", p_certificate_name.c_str()); + delete r; + return -1; + } + + return 0; +} // End of method store_certificate diff --git a/ccsrc/security/src/security_externals.cc b/ccsrc/security/src/security_externals.cc index 96d5b8d..452ce08 100644 --- a/ccsrc/security/src/security_externals.cc +++ b/ccsrc/security/src/security_externals.cc @@ -21,12 +21,12 @@ INTEGER LibSecurity__Certificates::fx__init__certs__db(const CHARSTRING& p_certs return ret; } -INTEGER LibSecurity__Certificates::fx__load__certificate(const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name) { +INTEGER LibSecurity__Certificates::fx__load__certificate(const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd) { loggers::get_instance().log_msg(">>> fx__load__certificate: ", p_certificate_name); loggers::get_instance().log_msg(">>> fx__load__certificate: ", p_private_key_name); const X509* certificate; - int ret = _security_services->load_certificate(std::string(static_cast(p_certificate_name)), std::string(static_cast(p_private_key_name)), &certificate); + int ret = _security_services->load_certificate(std::string(static_cast(p_certificate_name)), std::string(static_cast(p_private_key_name)), std::string(static_cast(p_private_key_passwd)), &certificate); loggers::get_instance().log("fx__load__certificate: certificate: '%p'", certificate); if (ret == 0) { ASN1_INTEGER* asn1_serial = ::X509_get_serialNumber((X509*)certificate); @@ -69,14 +69,25 @@ OCTETSTRING LibSecurity__Hash::fx__hash(const OCTETSTRING& p_to_be_hashed, const return hash; } -INTEGER LibSecurity__Signature::fx__sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem) { +INTEGER LibSecurity__Signature::fx__sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_signed_canonicalized) { loggers::get_instance().log_msg(">>> fx__sign: ", p_encoded_message); - if (_security_services->do_sign(p_encoded_message, p_certificate_name, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem) == -1) { + if (_security_services->do_sign(p_encoded_message, p_certificate_name, p_private_key_name, p_private_key_passwd, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem, p_pull_request_signed_canonicalized) == -1) { loggers::get_instance().log("fx__sign: Failed to signed message"); return -1; } return 0; } + +BOOLEAN LibSecurity__Signature::fx__do__sign__verify(const CHARSTRING& p_message, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate) { + loggers::get_instance().log(">>> fx__do__sign__verify"); + + if (!_security_services->do_sign_verify(p_message, p_canonicalization_method, p_signature_method, p_digest_method, p_digest_value, p_signature_value, p_subject_name, p_certificate)) { + loggers::get_instance().log("fx__do__sign__verify: Failed to verify message signature"); + return false; + } + + return true; +} \ No newline at end of file diff --git a/ccsrc/security/src/securty_services.cc b/ccsrc/security/src/securty_services.cc index 0103af5..cca8948 100644 --- a/ccsrc/security/src/securty_services.cc +++ b/ccsrc/security/src/securty_services.cc @@ -2,6 +2,8 @@ #include #include +#include "converter.hh" + #include "loggers.hh" #include "xml_converters.hh" @@ -28,45 +30,49 @@ int security_services::initialize(const std::string& p_certs_db_path) { return 0; } -int security_services::load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const X509** p_certificate) { +int security_services::load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, const X509** p_certificate) { loggers::get_instance().log("security_services::load_certificate: '%s'", p_certificate_name.c_str()); loggers::get_instance().log("security_services::load_certificate: '%s'", p_private_key_name.c_str()); + loggers::get_instance().log("security_services::load_certificate: '%s'", p_private_key_passwd.c_str()); - return _certs_db->get_certificate(p_certificate_name, p_private_key_name, p_certificate); + return _certs_db->get_certificate(p_certificate_name, p_private_key_name, p_private_key_passwd, p_certificate); } -int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem) { +int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_signed_canonicalized) { loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_encoded_message); loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_certificate_name); + loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_private_key_name); + loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_private_key_passwd); // Canonicalization std::string canonicalized; xml_converters::get_instance().xml_canonicalization(std::string((const char*)(static_cast(p_encoded_message)), p_encoded_message.lengthof()), canonicalized); - OCTETSTRING encoded_message(char2oct(CHARSTRING(canonicalized.c_str()))); - loggers::get_instance().log("security_services::do_sign: canonicalized: '%s", canonicalized.c_str()); + p_pull_request_signed_canonicalized = CHARSTRING(canonicalized.c_str()); + OCTETSTRING encoded_message(char2oct(p_pull_request_signed_canonicalized)); + loggers::get_instance().log_msg("security_services::do_sign: p_pull_request_signed_canonicalized: ", p_pull_request_signed_canonicalized); // Retrieve certificate std::string certificate_id; if (certs_loader::get_instance().get_certificate_id(std::string(static_cast(p_certificate_name)), certificate_id) != 0) { - loggers::get_instance().warning("fx__sign: Failed to retrieve certificate identifier"); + loggers::get_instance().warning("security_services::do_sign: Failed to retrieve certificate identifier"); return -1; } - loggers::get_instance().log("fx__sign: certificate_id: '%s'", certificate_id.c_str()); + loggers::get_instance().log("security_services::do_sign: certificate_id: '%s'", certificate_id.c_str()); const X509* certificate; if (_certs_db->get_certificate(certificate_id, &certificate) != 0) { - loggers::get_instance().warning("fx__sign: Failed to retrieve certificate"); + loggers::get_instance().warning("security_services::do_sign: Failed to retrieve certificate"); return -1; } X509_NAME* sn = X509_get_subject_name((X509*)certificate); std::string subject(512, (char)0x00); - X509_NAME_oneline(sn, (char*)subject.c_str(), subject.length()); - loggers::get_instance().log("fx__sign: certificate_id: X509_NAME_oneline: '%s'", subject.c_str()); + ::X509_NAME_oneline(sn, (char*)subject.c_str(), subject.length()); + loggers::get_instance().log("security_services::do_sign: X509_NAME_oneline: '%s'", subject.c_str()); p_x509_certificate_subject = CHARSTRING(subject.c_str()); X509_free((X509*)certificate); std::string str; if (_certs_db->get_certificate_pem(certificate_id, str) != 0) { - loggers::get_instance().warning("fx__sign: Failed to retrieve certificate PEM"); + loggers::get_instance().warning("security_services::do_sign: Failed to retrieve certificate PEM"); return -1; } p_x509_certificate_pem = CHARSTRING(str.c_str()); @@ -74,45 +80,45 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARS // Compute the digest sha256 digest; digest.generate(char2oct(CHARSTRING(canonicalized.c_str())), p_digest); - loggers::get_instance().log_msg("fx__sign: certificate_id: p_digest: ", p_digest); + loggers::get_instance().log_msg("security_services::do_sign: p_digest: ", p_digest); // Retrive the private key const EVP_PKEY* private_key; int ret = _certs_db->get_private_key(certificate_id, &private_key); if (ret == 1) { - loggers::get_instance().warning("fx__sign: Failed to retrieve private key"); + loggers::get_instance().warning("security_services::do_sign: Failed to retrieve private key"); return -1; } - loggers::get_instance().log("fx__sign: certificate_id: private_key: '%p'", private_key); + loggers::get_instance().log("security_services::do_sign: private_key: '%p'", private_key); // Create signing context EVP_MD_CTX* ctx = ::EVP_MD_CTX_new(); if (ctx == NULL) { - loggers::get_instance().warning("fx__sign: EVP_MD_CTX_create failed, error 0x%lx", ::ERR_get_error()); + loggers::get_instance().warning("security_services::do_sign: EVP_MD_CTX_create failed, error 0x%lx", ::ERR_get_error()); return -1; } if (::EVP_DigestSignInit(ctx, NULL, EVP_sha256(), NULL, (EVP_PKEY*)private_key) != 1) { // FIXME Add parameter to chose the digest algorithm - loggers::get_instance().warning("fx__sign: EVP_DigestSignInit failed, error 0x%lx", ::ERR_get_error()); + loggers::get_instance().warning("security_services::do_sign: EVP_DigestSignInit failed, error 0x%lx", ::ERR_get_error()); ::EVP_MD_CTX_free(ctx); return -1; } if (::EVP_DigestSignUpdate(ctx, (const unsigned char*)canonicalized.c_str(), canonicalized.length()) != 1) { - loggers::get_instance().warning("fx__sign: EVP_DigestSignUpdate failed, error 0x%lx", ::ERR_get_error()); + loggers::get_instance().warning("security_services::do_sign: EVP_DigestSignUpdate failed, error 0x%lx", ::ERR_get_error()); ::EVP_MD_CTX_free(ctx); return -1; } // Get signature lengthof size_t signature_length = 0; if (::EVP_DigestSignFinal(ctx, NULL, &signature_length) != 1) { - loggers::get_instance().warning("fx__sign: EVP_DigestSignUpdate failed, error 0x%lx", ::ERR_get_error()); + loggers::get_instance().warning("security_services::do_sign: EVP_DigestSignUpdate failed, error 0x%lx", ::ERR_get_error()); ::EVP_MD_CTX_free(ctx); return -1; } - loggers::get_instance().log("fx__sign: signature_length: %d", signature_length); + loggers::get_instance().log("security_services::do_sign: signature_length: %d", signature_length); std::vector s(signature_length, 0x00); unsigned char* val = s.data(); if (::EVP_DigestSignFinal(ctx, val, &signature_length) != 1) { - loggers::get_instance().warning("fx__sign: EVP_DigestSignUpdate failed, error 0x%lx", ::ERR_get_error()); + loggers::get_instance().warning("security_services::do_sign: EVP_DigestSignUpdate failed, error 0x%lx", ::ERR_get_error()); ::EVP_MD_CTX_free(ctx); s.clear(); return -1; @@ -121,7 +127,109 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARS p_signature = OCTETSTRING(signature_length, s.data()); ::EVP_MD_CTX_free(ctx); - loggers::get_instance().log_msg("fx__sign: signature: ", p_signature); + loggers::get_instance().log_msg("<<< security_services::do_sign: signature: ", p_signature); return 0; -} \ No newline at end of file +} + +bool security_services::do_sign_verify(const CHARSTRING& p_message, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate) { + loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_message: ", p_message); + loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_canonicalization_method: ", p_canonicalization_method); + loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_subject_name: ", p_subject_name); + loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_signature_method: ", p_signature_method); + + // Compute the digest + sha256 digest; + OCTETSTRING dg; + digest.generate(char2oct(p_message), dg); + loggers::get_instance().log_msg("security_services::do_sign_verify: digest: ", dg); + + // Retrieve certificate + std::string sn(static_cast(unichar2char(p_subject_name))); + std::string certificate_id; + const X509* certificate; + if (_certs_db->get_certificate_by_subject_name(sn, &certificate) != 0) { + loggers::get_instance().warning("security_services::do_sign_verify: Failed to retrieve certificate"); + // Use provided certificate if any + size_t i = sn.find_first_of("CN="); + if (i == std::string::npos) { + loggers::get_instance().warning("security_services::do_sign_verify: Failed to extract certificate name"); + return false; + } + size_t j = sn.find_first_of(","); + std::string certificate_name = sn.substr(i + 3, j - i - 3); + loggers::get_instance().log("security_services::do_sign_verify: certificate name: '%s'", certificate_name.c_str()); + const certs_db_record* record; + if (_certs_db->store_certificate(certificate_name, std::string(static_cast(unichar2char(p_certificate))), certificate_id, &record) == -1) { + loggers::get_instance().warning("security_services::do_sign_verify: Failed to store certificate"); + return false; + } + loggers::get_instance().log("security_services::do_sign_verify: certificate id: '%s'", record->certificate_id().c_str()); + } + + // Retrive the public key + const EVP_PKEY* public_key; + int ret = _certs_db->get_public_keys(certificate_id, &public_key); + if (ret == 1) { + loggers::get_instance().warning("security_services::do_sign_verify: Failed to retrieve public key"); + return false; + } + loggers::get_instance().log("security_services::do_sign: public_key: '%p'", public_key); + + // Create signing context + EVP_MD_CTX* ctx = ::EVP_MD_CTX_new(); + if (ctx == NULL) { + loggers::get_instance().warning("security_services::do_sign_verify: EVP_MD_CTX_create failed, error 0x%lx", ::ERR_get_error()); + return false; + } + std::string signature_method(static_cast(unichar2char(p_signature_method))); // E.g. http://www.w3.org/2000/09/xmldsig#rsa-sha1 + const EVP_MD *md; + if (signature_method.find("sha1") != std::string::npos) { + md = EVP_sha1(); + } else if (signature_method.find("sha256") != std::string::npos) { + md = EVP_sha256(); + } else if (signature_method.find("sha384") != std::string::npos) { + md = EVP_sha384(); + } else { + return false; + } + if (::EVP_DigestVerifyInit(ctx, NULL, md, NULL, (EVP_PKEY*)public_key) != 1) { // FIXME Add parameter to chose the digest algorithm + loggers::get_instance().warning("security_services::do_sign_verify: EVP_DigestVerifyInit failed, error 0x%lx", ::ERR_get_error()); + ::EVP_MD_CTX_free(ctx); + return false; + } + std::string signature_value(static_cast(unichar2char(p_signature_value))); + // Remove CR/LF if any + //signature_value.erase(std::remove(signature_value.begin(), signature_value.end(), '\r'), signature_value.end()); + //signature_value.erase(std::remove(signature_value.begin(), signature_value.end(), '\n'), signature_value.end()); + loggers::get_instance().warning("security_services::do_sign_verify: Before B64 decoded: '%s'", signature_value.c_str()); + // Convert into bytes buffer + const std::vector to_decode((const unsigned char*)signature_value.c_str(), static_cast((const unsigned char*)signature_value.c_str() + signature_value.length())); + std::vector b64 = converter::get_instance().base64_to_buffer(to_decode); + loggers::get_instance().warning("security_services::do_sign_verify: B64 decoded: '%s'", converter::get_instance().bytes_to_hexa(b64, true).c_str()); + + + // EVP_ENCODE_CTX *ctx_ = ::EVP_ENCODE_CTX_new(); + // ::EVP_DecodeInit(ctx_); + // std::vector b64_(1024, 0x00); + // int outl1 = 0; + // int outl2 = 0; + // ::EVP_DecodeUpdate(ctx_, b64_.data(), &outl1, to_decode.data(), to_decode.size()); + // ::EVP_DecodeFinal(ctx_, b64_.data(), &outl2); + // ::EVP_ENCODE_CTX_free(ctx_); + // b64_.resize(outl1 + outl2); + // loggers::get_instance().log("security_services::do_sign_verify: B64_ decoded: '%s'", converter::get_instance().bytes_to_hexa(b64_, true).c_str()); + + + + // Check signature + if(::EVP_DigestVerifyFinal(ctx, b64.data(), b64.size()) != 1) { + loggers::get_instance().warning("security_services::do_sign_verify: EVP_DigestVerifyFinal failed, error 0x%lx", ::ERR_get_error()); + ::EVP_MD_CTX_free(ctx); + return false; + } + + ::EVP_MD_CTX_free(ctx); + + return true; +} diff --git a/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn b/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn index 147f0c3..567df6c 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn @@ -6,13 +6,17 @@ module LibHttp_XmlMessageBodyTypes { */ // TODO Add here your custom RFCs import - type union XmlBody { + type union XmlBodyMsg { // TODO Add here your custom variants - charstring raw } with { variant "" } + type record XmlBody { + XmlBodyMsg msg, + charstring raw optional + } + } with { variant "" } // End of LibHttp_XmlMessageBodyTypes diff --git a/ttcn/LibSecurity/ttcn/LibSecurity_Certificates.ttcn b/ttcn/LibSecurity/ttcn/LibSecurity_Certificates.ttcn index 4fba516..4af7399 100644 --- a/ttcn/LibSecurity/ttcn/LibSecurity_Certificates.ttcn +++ b/ttcn/LibSecurity/ttcn/LibSecurity_Certificates.ttcn @@ -2,14 +2,14 @@ module LibSecurity_Certificates { external function fx_init_certs_db(in charstring p_certs_db_path) return integer; - external function fx_load_certificate(in charstring p_certificate_name, in charstring p_private_key_name) return integer; + external function fx_load_certificate(in charstring p_certificate_name, in charstring p_private_key_name, in charstring p_private_key_passwd) return integer; function f_init_certs_db(in charstring p_certs_db_path) return integer { return fx_init_certs_db(p_certs_db_path); } - function f_load_certificate(in charstring p_certificate_name, in charstring p_private_key_name) return integer { - return fx_load_certificate(p_certificate_name, p_private_key_name); + function f_load_certificate(in charstring p_certificate_name, in charstring p_private_key_name, in charstring p_private_key_passwd) return integer { + return fx_load_certificate(p_certificate_name, p_private_key_name, p_private_key_passwd); } } // End of LibSecurity_Certificates \ No newline at end of file diff --git a/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn b/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn index 614caf6..198c03c 100644 --- a/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn +++ b/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn @@ -1,26 +1,52 @@ module LibSecurity_Signature { - import from LibSecurity_Hash all; - /** - * @desc + * @desc Sign message * @param [in] p_encoded_message The raw message to be signed - * @param [in] p_hash_algorithm The Hash algorithm to use * @param [in] p_certificate_name The certificate to use for the signature - * @param [in] p_signature The raw signature + * @param [in] p_private_key_name The private key to use for the signature, in PCKS#8 format + * @param [in] p_private_key_passwd The password tpo decrypt the private key. Empty if no encryption + * @param [out] p_signature The raw signature + * @param [out] p_digest The Hash algorithm to use + * @param [out] p_x509_certificate_subject The certificate subject + * @param [out] p_x509_certificate_pem The certificate in PEM format * @return 0 on success, -1 otherwise */ function f_sign( in octetstring p_encoded_message, - in charstring p_certificate_name, + in charstring p_certificate_name, + in charstring p_private_key_name, + in charstring p_private_key_passwd, out octetstring p_signature, out octetstring p_digest, out charstring p_x509_certificate_subject, - out charstring p_x509_certificate_pem + out charstring p_x509_certificate_pem, + out charstring p_pull_request_signed_canonicalized ) return integer { - return fx_sign(p_encoded_message, p_certificate_name, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem); + return fx_sign(p_encoded_message, p_certificate_name, p_private_key_name, p_private_key_passwd, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem, p_pull_request_signed_canonicalized); + } + + external function fx_sign(in octetstring p_encoded_message, in charstring p_certificate_name, in charstring p_private_key_name, in charstring p_private_key_passwd, out octetstring p_signature, out octetstring p_digest, out charstring p_x509_certificate_subject, out charstring p_x509_certificate_pem, out charstring p_pull_request_signed_canonicalized) return integer; + + /** + * @desc Verify signature + * @param [in] p_message The raw message to be verified + * @param [in] TODO + * @return true on success, false otherwise + */ + function f_do_sign_verify( + in charstring p_message, + in universal charstring p_canonicalization_method, + in universal charstring p_signature_method, + in universal charstring p_digest_method, + in universal charstring p_digest_value, + in universal charstring p_signature_value, + in universal charstring p_subject_name, + in universal charstring p_certificate + ) return boolean { + return fx_do_sign_verify(p_message, p_canonicalization_method, p_signature_method, p_digest_method, p_digest_value, p_signature_value, p_subject_name, p_certificate); } - external function fx_sign(in octetstring p_encoded_message, in charstring p_certificate_name, out octetstring p_signature, out octetstring p_digest, out charstring p_x509_certificate_subject, out charstring p_x509_certificate_pem) return integer; + external function fx_do_sign_verify(in charstring p_message, in universal charstring p_canonicalization_method, in universal charstring p_signature_method, in universal charstring p_digest_method, in universal charstring p_digest_value, in universal charstring p_signature_value, in universal charstring p_subject_name, in universal charstring p_certificate) return boolean; } // End of LibSecurity_Signature \ No newline at end of file -- GitLab From 3c00b81c1e158922c83ae0c0de5288631dd1a2be Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Tue, 14 Feb 2023 13:53:11 +0100 Subject: [PATCH 11/37] Bug fixed in LibHttp_XmlMessageBodyTypes.ttcn --- ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn | 1 + 1 file changed, 1 insertion(+) diff --git a/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn b/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn index 567df6c..b82bee9 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn @@ -8,6 +8,7 @@ module LibHttp_XmlMessageBodyTypes { type union XmlBodyMsg { // TODO Add here your custom variants + charstring raw } with { variant "" } -- GitLab From be17c52ee932ef40c9295b9bef56715d991769b0 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Thu, 16 Feb 2023 08:46:21 +0100 Subject: [PATCH 12/37] Validate XML envelopped signature mechanism --- ccsrc/Framework/include/converter.hh | 9 ++ ccsrc/Framework/src/converter.cc | 10 ++ ccsrc/security/include/certs_cache.hh | 5 + ccsrc/security/include/certs_db_record.hh | 1 + ccsrc/security/include/security_services.hh | 7 +- ccsrc/security/src/certs_cache.cc | 56 ++++++++++- ccsrc/security/src/security_externals.cc | 4 +- ccsrc/security/src/securty_services.cc | 96 ++++++++++++------- .../ttcn/LibSecurity_Signature.ttcn | 7 +- 9 files changed, 150 insertions(+), 45 deletions(-) diff --git a/ccsrc/Framework/include/converter.hh b/ccsrc/Framework/include/converter.hh index 7f2adeb..cdb29e9 100644 --- a/ccsrc/Framework/include/converter.hh +++ b/ccsrc/Framework/include/converter.hh @@ -366,6 +366,15 @@ public: */ std::vector split_arguments_line(const std::string& p_value); + /*! + * \brief Replace string or character into the the provided string + * \param[in] p_value The original string value + * \param[in] p_from The pattern to be replaced + * \param[in] p_to The new pattern + * \return The modified string + */ + std::string replace(const std::string& p_value, const std::string& p_from, const std::string& p_to); + /*! * \brief Convert the provided buffer into a Base64 * \param[in] p_value The buffer value diff --git a/ccsrc/Framework/src/converter.cc b/ccsrc/Framework/src/converter.cc index 0b2f376..9df0ad9 100644 --- a/ccsrc/Framework/src/converter.cc +++ b/ccsrc/Framework/src/converter.cc @@ -187,6 +187,16 @@ static std::string insert_linebreaks(std::string str, size_t distance) { return str; } +std::string converter::replace(const std::string& p_value, const std::string& p_from, const std::string& p_to) { + size_t start_pos = 0; + std::string str(p_value); + while((start_pos = str.find(p_from, start_pos)) != std::string::npos) { + str.replace(start_pos, p_from.length(), p_to); + start_pos += p_to.length(); // Handles case where 'p_to' is a substring of 'p_from' + } + return str; +} + std::vector converter::buffer_to_base64(const std::vector &p_value, const bool p_is_url) { const std::string& base64_enc_map_ = converter::base64_enc_map[(p_is_url) ? 1 : 0]; const unsigned char trailing_char = (p_is_url) ? '.' : '='; diff --git a/ccsrc/security/include/certs_cache.hh b/ccsrc/security/include/certs_cache.hh index 70e24a3..085872a 100644 --- a/ccsrc/security/include/certs_cache.hh +++ b/ccsrc/security/include/certs_cache.hh @@ -85,6 +85,11 @@ public: /*! \publicsection */ void dump() const; + const std::string cert_to_string(const std::string& p_certificate_id); + + int publickey_to_string(const EVP_PKEY* p_public_kep, std::vector& p_buffer); + + private: /*! \privatesection */ /*! * \fn int load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, const certs_db_record** p_record); diff --git a/ccsrc/security/include/certs_db_record.hh b/ccsrc/security/include/certs_db_record.hh index 302b0f8..772493a 100644 --- a/ccsrc/security/include/certs_db_record.hh +++ b/ccsrc/security/include/certs_db_record.hh @@ -62,5 +62,6 @@ public: /*! \publicsection */ inline const EVP_PKEY* private_key() const { return _private_key; }; inline const EVP_PKEY* public_key() const { return ::X509_get_pubkey(_certificate); }; inline const X509_NAME* subject_name() const { return ::X509_get_subject_name(_certificate); }; + inline const X509_NAME* issuer() const { return ::X509_get_issuer_name(_certificate); }; inline const std::string& pem() const { return _pem; }; }; // End of class certs_db_record diff --git a/ccsrc/security/include/security_services.hh b/ccsrc/security/include/security_services.hh index 55befe0..f8c7bf0 100644 --- a/ccsrc/security/include/security_services.hh +++ b/ccsrc/security/include/security_services.hh @@ -45,10 +45,7 @@ public: /*! \publicsection */ * \fn int do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem); * \brief Sign message * \param[in] p_encoded_message The raw message to be signed - * \param[in] p_encoded_message The raw message to be signed - * \param[in] p_encoded_message The raw message to be signed - * \param[in] p_encoded_message The raw message to be signed - * \param[in] p_encoded_message The raw message to be signed + * \param[in] TODO The raw message to be signed * \return 0 on success, -1 otherwise */ int do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_signed_canonicalized); @@ -59,5 +56,5 @@ public: /*! \publicsection */ * \param[in] TODO * \return true on success, false otherwise */ - bool do_sign_verify(const CHARSTRING& p_message, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate); + bool do_sign_verify(const CHARSTRING& p_message, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate, const CHARSTRING& p_debug_message); }; \ No newline at end of file diff --git a/ccsrc/security/src/certs_cache.cc b/ccsrc/security/src/certs_cache.cc index c41d7b0..761fbb0 100644 --- a/ccsrc/security/src/certs_cache.cc +++ b/ccsrc/security/src/certs_cache.cc @@ -72,10 +72,10 @@ int certs_cache::load_certificate(const std::string& p_certificate_name, const s *p_record = it->second.get(); // Mapping certificate id/certificate name _certificates_idx.insert(std::pair(certificate_id, p_certificate_name)); - std::string sn(512, (char)0x00); + std::string sn(256, (char)0x00); const X509_NAME* subject = (*p_record)->subject_name(); ::X509_NAME_oneline(subject, sn.data(), sn.length()); - loggers::get_instance().log("certs_cache::load_certificate: sn: '%s'", sn.c_str()); + loggers::get_instance().log("certs_cache::load_certificate: sn: '%s'", sn.c_str()); _certificates_subject.insert(std::pair(sn, certificate_id)); } else { // Certificate is on the DB, load it @@ -191,7 +191,7 @@ int certs_cache::store_certificate(const std::string& p_certificate_name, const *p_record = it->second.get(); // Mapping certificate id/certificate name _certificates_idx.insert(std::pair(p_certificate_id, p_certificate_name)); - std::string sn(512, (char)0x00); + std::string sn(256, (char)0x00); const X509_NAME* subject = (*p_record)->subject_name(); ::X509_NAME_oneline(subject, sn.data(), sn.length()); loggers::get_instance().log("certs_cache::store_certificate: sn: '%s'", sn.c_str()); @@ -207,3 +207,53 @@ void certs_cache::dump() const { const certs_db_record *p = it->second.get(); } // End of 'for' statement } // End of method dump + +const std::string certs_cache::cert_to_string(const std::string& p_certificate_id) { + loggers::get_instance().log(">>> certs_cache::cert_to_string: '%s'", p_certificate_id.c_str()); + + const certs_db_record* record; + if (load_certificate(p_certificate_id, &record) == -1) { + loggers::get_instance().warning("certs_cache::cert_to_string: Failed to load certificate"); + return std::string(::ERR_error_string(::ERR_get_error(), nullptr));; + } + + BIO* bio = ::BIO_new(::BIO_s_mem()); + if (bio == nullptr) { + loggers::get_instance().warning("certs_cache::cert_to_string: Failed to dunp certificate"); + return std::string(::ERR_error_string(::ERR_get_error(), nullptr)); + } + + if (::PEM_write_bio_X509(bio, (X509*)record->certificate()) == 0) { + ::BIO_free(bio); + loggers::get_instance().warning("certs_cache::cert_to_string: Failed to dunp certificate"); + return std::string(::ERR_error_string(::ERR_get_error(), nullptr)); + } + + size_t len = ::BIO_get_mem_data(bio, nullptr); + std::string s(len, 0x00); + ::BIO_read(bio, s.data(), len); + ::BIO_free(bio); + loggers::get_instance().log("certs_cache::cert_to_string: dump: '%s'", s.c_str()); + + return s; +} + +int certs_cache::publickey_to_string(const EVP_PKEY* p_public_kep, std::vector& p_buffer) { + loggers::get_instance().log(">>> certs_cache::publickey_to_string: '%p'", p_public_kep); + + unsigned char buffer[512]; + unsigned char* ptr = &buffer[0]; + int ret = ::i2d_PublicKey((EVP_PKEY*)p_public_kep, &ptr); + loggers::get_instance().log("certs_cache::publickey_to_string: ret: '%d'", ret); + if (ret < 0) { + loggers::get_instance().warning("certs_cache::publickey_to_string: Failed to dunp certificate"); + p_buffer.clear(); + return -1; + } + + p_buffer.assign((unsigned char*)buffer, (unsigned char*)(buffer + ret)); + loggers::get_instance().log("certs_cache::publickey_to_string: p_buffer len: '%d'", p_buffer.size()); + loggers::get_instance().log("certs_cache::publickey_to_string: dump: '%s'", converter::get_instance().bytes_to_hexa(p_buffer).c_str()); + + return 0; +} \ No newline at end of file diff --git a/ccsrc/security/src/security_externals.cc b/ccsrc/security/src/security_externals.cc index 452ce08..bc7446e 100644 --- a/ccsrc/security/src/security_externals.cc +++ b/ccsrc/security/src/security_externals.cc @@ -80,10 +80,10 @@ INTEGER LibSecurity__Signature::fx__sign(const OCTETSTRING& p_encoded_message, c return 0; } -BOOLEAN LibSecurity__Signature::fx__do__sign__verify(const CHARSTRING& p_message, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate) { +BOOLEAN LibSecurity__Signature::fx__do__sign__verify(const CHARSTRING& p_message, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate, const CHARSTRING& p_debug_message) { loggers::get_instance().log(">>> fx__do__sign__verify"); - if (!_security_services->do_sign_verify(p_message, p_canonicalization_method, p_signature_method, p_digest_method, p_digest_value, p_signature_value, p_subject_name, p_certificate)) { + if (!_security_services->do_sign_verify(p_message, p_canonicalization_method, p_signature_method, p_digest_method, p_digest_value, p_signature_value, p_subject_name, p_certificate, p_debug_message)) { loggers::get_instance().log("fx__do__sign__verify: Failed to verify message signature"); return false; } diff --git a/ccsrc/security/src/securty_services.cc b/ccsrc/security/src/securty_services.cc index cca8948..aded5e9 100644 --- a/ccsrc/security/src/securty_services.cc +++ b/ccsrc/security/src/securty_services.cc @@ -63,12 +63,12 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARS loggers::get_instance().warning("security_services::do_sign: Failed to retrieve certificate"); return -1; } + loggers::get_instance().log("security_services::do_sign: certificate dump: '%s'", _certs_db->cert_to_string(certificate_id).c_str()); X509_NAME* sn = X509_get_subject_name((X509*)certificate); std::string subject(512, (char)0x00); ::X509_NAME_oneline(sn, (char*)subject.c_str(), subject.length()); loggers::get_instance().log("security_services::do_sign: X509_NAME_oneline: '%s'", subject.c_str()); p_x509_certificate_subject = CHARSTRING(subject.c_str()); - X509_free((X509*)certificate); std::string str; if (_certs_db->get_certificate_pem(certificate_id, str) != 0) { @@ -80,7 +80,7 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARS // Compute the digest sha256 digest; digest.generate(char2oct(CHARSTRING(canonicalized.c_str())), p_digest); - loggers::get_instance().log_msg("security_services::do_sign: p_digest: ", p_digest); + loggers::get_instance().log_msg("security_services::do_sign: digest: ", p_digest); // Retrive the private key const EVP_PKEY* private_key; @@ -114,26 +114,53 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARS ::EVP_MD_CTX_free(ctx); return -1; } + if (signature_length != ::EVP_PKEY_size(private_key)) { + loggers::get_instance().warning("security_services::do_sign: Wrong signature length"); + ::EVP_MD_CTX_free(ctx); + return -1; + } loggers::get_instance().log("security_services::do_sign: signature_length: %d", signature_length); std::vector s(signature_length, 0x00); - unsigned char* val = s.data(); - if (::EVP_DigestSignFinal(ctx, val, &signature_length) != 1) { + if (::EVP_DigestSignFinal(ctx, s.data(), &signature_length) != 1) { loggers::get_instance().warning("security_services::do_sign: EVP_DigestSignUpdate failed, error 0x%lx", ::ERR_get_error()); ::EVP_MD_CTX_free(ctx); s.clear(); return -1; } + ::EVP_MD_CTX_free(ctx); + + // Ensure that the signature round-trips + // Retrive the public key + const EVP_PKEY* public_key; + if (_certs_db->get_private_key(certificate_id, &public_key) == 1) { + loggers::get_instance().warning("security_services::do_sign: Failed to retrieve private key"); + return -1; + } + loggers::get_instance().log("security_services::do_sign: public_key: '%p'", public_key); + std::vector buffer; + _certs_db->publickey_to_string(public_key, buffer); + ctx = ::EVP_MD_CTX_new(); + if (!::EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, (EVP_PKEY*)public_key) || + !::EVP_DigestVerifyUpdate(ctx, (const unsigned char*)canonicalized.c_str(), canonicalized.length()) || + !::EVP_DigestVerifyFinal(ctx, s.data(), s.size())) { + loggers::get_instance().warning("security_services::do_sign: Failed to verify signature, error 0x%lx", ::ERR_get_error()); + ::EVP_MD_CTX_free(ctx); + s.clear(); + return -1; + } + ::EVP_MD_CTX_free(ctx); + loggers::get_instance().log("security_services::do_sign: signature was verified with public key"); p_signature = OCTETSTRING(signature_length, s.data()); - ::EVP_MD_CTX_free(ctx); loggers::get_instance().log_msg("<<< security_services::do_sign: signature: ", p_signature); return 0; } -bool security_services::do_sign_verify(const CHARSTRING& p_message, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate) { - loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_message: ", p_message); +bool security_services::do_sign_verify(const CHARSTRING& p_message, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate, const CHARSTRING& p_debug_message) { + loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_message: ", p_message); + loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_debug_message: ", p_debug_message); loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_canonicalization_method: ", p_canonicalization_method); loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_subject_name: ", p_subject_name); loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_signature_method: ", p_signature_method); @@ -151,13 +178,20 @@ bool security_services::do_sign_verify(const CHARSTRING& p_message, const UNIVER if (_certs_db->get_certificate_by_subject_name(sn, &certificate) != 0) { loggers::get_instance().warning("security_services::do_sign_verify: Failed to retrieve certificate"); // Use provided certificate if any - size_t i = sn.find_first_of("CN="); + loggers::get_instance().log("security_services::do_sign_verify: sn='%s'", sn.c_str()); + size_t i = sn.find("CN="); if (i == std::string::npos) { loggers::get_instance().warning("security_services::do_sign_verify: Failed to extract certificate name"); return false; } - size_t j = sn.find_first_of(","); - std::string certificate_name = sn.substr(i + 3, j - i - 3); + size_t j = sn.find(",", i + 3); + std::string certificate_name; + if (j == std::string::npos) { + certificate_name = sn.substr(i + 3); + } else { + certificate_name = sn.substr(i + 3, j - i - 3); + } + certificate_name = converter::get_instance().replace(certificate_name, "-", "_"); loggers::get_instance().log("security_services::do_sign_verify: certificate name: '%s'", certificate_name.c_str()); const certs_db_record* record; if (_certs_db->store_certificate(certificate_name, std::string(static_cast(unichar2char(p_certificate))), certificate_id, &record) == -1) { @@ -166,6 +200,7 @@ bool security_services::do_sign_verify(const CHARSTRING& p_message, const UNIVER } loggers::get_instance().log("security_services::do_sign_verify: certificate id: '%s'", record->certificate_id().c_str()); } + loggers::get_instance().log("security_services::do_sign_verify: certificate dump: '%s'", _certs_db->cert_to_string(certificate_id).c_str()); // Retrive the public key const EVP_PKEY* public_key; @@ -174,7 +209,9 @@ bool security_services::do_sign_verify(const CHARSTRING& p_message, const UNIVER loggers::get_instance().warning("security_services::do_sign_verify: Failed to retrieve public key"); return false; } - loggers::get_instance().log("security_services::do_sign: public_key: '%p'", public_key); + loggers::get_instance().log("security_services::do_sign_verify: public_key: '%p'", public_key); + std::vector buffer; + _certs_db->publickey_to_string(public_key, buffer); // Create signing context EVP_MD_CTX* ctx = ::EVP_MD_CTX_new(); @@ -185,46 +222,41 @@ bool security_services::do_sign_verify(const CHARSTRING& p_message, const UNIVER std::string signature_method(static_cast(unichar2char(p_signature_method))); // E.g. http://www.w3.org/2000/09/xmldsig#rsa-sha1 const EVP_MD *md; if (signature_method.find("sha1") != std::string::npos) { - md = EVP_sha1(); + loggers::get_instance().log("security_services::do_sign_verify: signature method: sha1"); + md = EVP_sha1(); } else if (signature_method.find("sha256") != std::string::npos) { + loggers::get_instance().log("security_services::do_sign_verify: signature method: sha256"); md = EVP_sha256(); } else if (signature_method.find("sha384") != std::string::npos) { + loggers::get_instance().log("security_services::do_sign_verify: signature method: sha384"); md = EVP_sha384(); } else { + loggers::get_instance().error("security_services::do_sign_verify: Unsupported signature method"); return false; } - if (::EVP_DigestVerifyInit(ctx, NULL, md, NULL, (EVP_PKEY*)public_key) != 1) { // FIXME Add parameter to chose the digest algorithm + // Check signature + if (::EVP_DigestVerifyInit(ctx, NULL, md, NULL, (EVP_PKEY*)public_key) != 1) { loggers::get_instance().warning("security_services::do_sign_verify: EVP_DigestVerifyInit failed, error 0x%lx", ::ERR_get_error()); ::EVP_MD_CTX_free(ctx); return false; } + if(::EVP_DigestVerifyUpdate(ctx, (const char*)p_message, p_message.lengthof()) != 1) { + loggers::get_instance().warning("security_services::do_sign_verify: EVP_DigestVerifyUpdate failed, error 0x%lx - %s", ::ERR_get_error(), ::ERR_error_string(::ERR_get_error(), nullptr)); + ::EVP_MD_CTX_free(ctx); + return false; + } std::string signature_value(static_cast(unichar2char(p_signature_value))); // Remove CR/LF if any //signature_value.erase(std::remove(signature_value.begin(), signature_value.end(), '\r'), signature_value.end()); //signature_value.erase(std::remove(signature_value.begin(), signature_value.end(), '\n'), signature_value.end()); - loggers::get_instance().warning("security_services::do_sign_verify: Before B64 decoded: '%s'", signature_value.c_str()); + loggers::get_instance().log("security_services::do_sign_verify: Before B64 decoded: '%s'", signature_value.c_str()); // Convert into bytes buffer const std::vector to_decode((const unsigned char*)signature_value.c_str(), static_cast((const unsigned char*)signature_value.c_str() + signature_value.length())); std::vector b64 = converter::get_instance().base64_to_buffer(to_decode); - loggers::get_instance().warning("security_services::do_sign_verify: B64 decoded: '%s'", converter::get_instance().bytes_to_hexa(b64, true).c_str()); - - - // EVP_ENCODE_CTX *ctx_ = ::EVP_ENCODE_CTX_new(); - // ::EVP_DecodeInit(ctx_); - // std::vector b64_(1024, 0x00); - // int outl1 = 0; - // int outl2 = 0; - // ::EVP_DecodeUpdate(ctx_, b64_.data(), &outl1, to_decode.data(), to_decode.size()); - // ::EVP_DecodeFinal(ctx_, b64_.data(), &outl2); - // ::EVP_ENCODE_CTX_free(ctx_); - // b64_.resize(outl1 + outl2); - // loggers::get_instance().log("security_services::do_sign_verify: B64_ decoded: '%s'", converter::get_instance().bytes_to_hexa(b64_, true).c_str()); - - - - // Check signature + loggers::get_instance().log("security_services::do_sign_verify: B64 decoded: '%s'", converter::get_instance().bytes_to_hexa(b64, true).c_str()); + loggers::get_instance().log("security_services::do_sign_verify: B64 decoded len: '%d'", b64.size()); if(::EVP_DigestVerifyFinal(ctx, b64.data(), b64.size()) != 1) { - loggers::get_instance().warning("security_services::do_sign_verify: EVP_DigestVerifyFinal failed, error 0x%lx", ::ERR_get_error()); + loggers::get_instance().warning("security_services::do_sign_verify: EVP_DigestVerifyFinal failed, error 0x%lx - %s", ::ERR_get_error(), ::ERR_error_string(::ERR_get_error(), nullptr)); ::EVP_MD_CTX_free(ctx); return false; } diff --git a/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn b/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn index 198c03c..52bf3c5 100644 --- a/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn +++ b/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn @@ -42,11 +42,12 @@ module LibSecurity_Signature { in universal charstring p_digest_value, in universal charstring p_signature_value, in universal charstring p_subject_name, - in universal charstring p_certificate + in universal charstring p_certificate, + in charstring p_debug_message ) return boolean { - return fx_do_sign_verify(p_message, p_canonicalization_method, p_signature_method, p_digest_method, p_digest_value, p_signature_value, p_subject_name, p_certificate); + return fx_do_sign_verify(p_message, p_canonicalization_method, p_signature_method, p_digest_method, p_digest_value, p_signature_value, p_subject_name, p_certificate, p_debug_message); } - external function fx_do_sign_verify(in charstring p_message, in universal charstring p_canonicalization_method, in universal charstring p_signature_method, in universal charstring p_digest_method, in universal charstring p_digest_value, in universal charstring p_signature_value, in universal charstring p_subject_name, in universal charstring p_certificate) return boolean; + external function fx_do_sign_verify(in charstring p_message, in universal charstring p_canonicalization_method, in universal charstring p_signature_method, in universal charstring p_digest_method, in universal charstring p_digest_value, in universal charstring p_signature_value, in universal charstring p_subject_name, in universal charstring p_certificate, in charstring p_debug_message) return boolean; } // End of LibSecurity_Signature \ No newline at end of file -- GitLab From fce4d880afefa0c32a033eba6e4a7e28c4a075b1 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Tue, 21 Feb 2023 13:44:11 +0100 Subject: [PATCH 13/37] Build AtsCAM Release.2 --- ccsrc/security/module.mk | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ccsrc/security/module.mk b/ccsrc/security/module.mk index ac2c199..e05c42d 100644 --- a/ccsrc/security/module.mk +++ b/ccsrc/security/module.mk @@ -1,13 +1,13 @@ sources := \ src/security_externals.cc \ - src/sha1.cc \ - src/sha256.cc \ - src/sha384.cc \ - src/hmac.cc \ src/certs_db_record.cc \ src/certs_db.cc \ src/certs_cache.cc \ src/certs_loader.cc \ - src/securty_services.cc + src/securty_services.cc \ + src/sha1.cc \ + src/sha256.cc \ + src/sha384.cc \ + src/hmac.cc \ includes := ./include -- GitLab From b89ce8eb02f65124a98caed3f84a04fc24d6b482 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Thu, 23 Feb 2023 14:00:18 +0100 Subject: [PATCH 14/37] Enhance X509 security support --- ccsrc/security/include/certs_cache.hh | 6 +++--- ccsrc/security/include/security_services.hh | 2 +- ccsrc/security/src/security_externals.cc | 4 ++-- ccsrc/security/src/securty_services.cc | 8 ++++---- ttcn/LibHttp/module_cise.mk | 4 ++-- ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn | 6 +++--- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/ccsrc/security/include/certs_cache.hh b/ccsrc/security/include/certs_cache.hh index 085872a..5e55c71 100644 --- a/ccsrc/security/include/certs_cache.hh +++ b/ccsrc/security/include/certs_cache.hh @@ -83,11 +83,11 @@ public: /*! \publicsection */ */ virtual int clear(); - void dump() const; + void dump() const; // For debug purpose. To be removed - const std::string cert_to_string(const std::string& p_certificate_id); + const std::string cert_to_string(const std::string& p_certificate_id); // For debug purpose. To be removed - int publickey_to_string(const EVP_PKEY* p_public_kep, std::vector& p_buffer); + int publickey_to_string(const EVP_PKEY* p_public_kep, std::vector& p_buffer); // For debug purpose. To be removed private: /*! \privatesection */ diff --git a/ccsrc/security/include/security_services.hh b/ccsrc/security/include/security_services.hh index f8c7bf0..9c28a4d 100644 --- a/ccsrc/security/include/security_services.hh +++ b/ccsrc/security/include/security_services.hh @@ -48,7 +48,7 @@ public: /*! \publicsection */ * \param[in] TODO The raw message to be signed * \return 0 on success, -1 otherwise */ - int do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_signed_canonicalized); + int do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_canonicalized); /*! * \fn int build_path(const std::string& p_root_directory); * \brief Verify message signature diff --git a/ccsrc/security/src/security_externals.cc b/ccsrc/security/src/security_externals.cc index bc7446e..c8ec692 100644 --- a/ccsrc/security/src/security_externals.cc +++ b/ccsrc/security/src/security_externals.cc @@ -69,10 +69,10 @@ OCTETSTRING LibSecurity__Hash::fx__hash(const OCTETSTRING& p_to_be_hashed, const return hash; } -INTEGER LibSecurity__Signature::fx__sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_signed_canonicalized) { +INTEGER LibSecurity__Signature::fx__sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_canonicalized) { loggers::get_instance().log_msg(">>> fx__sign: ", p_encoded_message); - if (_security_services->do_sign(p_encoded_message, p_certificate_name, p_private_key_name, p_private_key_passwd, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem, p_pull_request_signed_canonicalized) == -1) { + if (_security_services->do_sign(p_encoded_message, p_certificate_name, p_private_key_name, p_private_key_passwd, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem, p_pull_request_canonicalized) == -1) { loggers::get_instance().log("fx__sign: Failed to signed message"); return -1; } diff --git a/ccsrc/security/src/securty_services.cc b/ccsrc/security/src/securty_services.cc index aded5e9..7562e4e 100644 --- a/ccsrc/security/src/securty_services.cc +++ b/ccsrc/security/src/securty_services.cc @@ -38,7 +38,7 @@ int security_services::load_certificate(const std::string& p_certificate_name, c return _certs_db->get_certificate(p_certificate_name, p_private_key_name, p_private_key_passwd, p_certificate); } -int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_signed_canonicalized) { +int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_canonicalized) { loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_encoded_message); loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_certificate_name); loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_private_key_name); @@ -47,9 +47,9 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARS // Canonicalization std::string canonicalized; xml_converters::get_instance().xml_canonicalization(std::string((const char*)(static_cast(p_encoded_message)), p_encoded_message.lengthof()), canonicalized); - p_pull_request_signed_canonicalized = CHARSTRING(canonicalized.c_str()); - OCTETSTRING encoded_message(char2oct(p_pull_request_signed_canonicalized)); - loggers::get_instance().log_msg("security_services::do_sign: p_pull_request_signed_canonicalized: ", p_pull_request_signed_canonicalized); + p_pull_request_canonicalized = CHARSTRING(canonicalized.c_str()); + OCTETSTRING encoded_message(char2oct(p_pull_request_canonicalized)); + loggers::get_instance().log_msg("security_services::do_sign: p_pull_request_canonicalized: ", p_pull_request_canonicalized); // Retrieve certificate std::string certificate_id; diff --git a/ttcn/LibHttp/module_cise.mk b/ttcn/LibHttp/module_cise.mk index 516c376..4811675 100644 --- a/ttcn/LibHttp/module_cise.mk +++ b/ttcn/LibHttp/module_cise.mk @@ -2,8 +2,6 @@ sources := \ ttcn/LibHttp_BinaryMessageBodyTypes.ttcn \ ttcn/LibHttp_EncdecDeclarations.ttcn \ ttcn/LibHttp_Functions.ttcn \ - ttcn/LibHttp_JsonMessageBodyTypes.ttcn \ - ttcn/LibHttp_JsonTemplates.ttcn \ ttcn/LibHttp_JSONTypes.ttcn \ ttcn/LibHttp_MessageBodyTypes.ttcn \ ttcn/LibHttp_Pics.ttcn \ @@ -17,3 +15,5 @@ sources := \ # Please, move and comment the module you need to overwrite tofit your project # ttcn/LibHttp_XmlMessageBodyTypes.ttcn \ # ttcn/LibHttp_XmlTemplates.ttcn +# ttcn/LibHttp_JsonMessageBodyTypes.ttcn \ +# ttcn/LibHttp_JsonTemplates.ttcn \ diff --git a/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn b/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn index 52bf3c5..74065a6 100644 --- a/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn +++ b/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn @@ -21,12 +21,12 @@ module LibSecurity_Signature { out octetstring p_digest, out charstring p_x509_certificate_subject, out charstring p_x509_certificate_pem, - out charstring p_pull_request_signed_canonicalized + out charstring p_pull_request_canonicalized ) return integer { - return fx_sign(p_encoded_message, p_certificate_name, p_private_key_name, p_private_key_passwd, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem, p_pull_request_signed_canonicalized); + return fx_sign(p_encoded_message, p_certificate_name, p_private_key_name, p_private_key_passwd, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem, p_pull_request_canonicalized); } - external function fx_sign(in octetstring p_encoded_message, in charstring p_certificate_name, in charstring p_private_key_name, in charstring p_private_key_passwd, out octetstring p_signature, out octetstring p_digest, out charstring p_x509_certificate_subject, out charstring p_x509_certificate_pem, out charstring p_pull_request_signed_canonicalized) return integer; + external function fx_sign(in octetstring p_encoded_message, in charstring p_certificate_name, in charstring p_private_key_name, in charstring p_private_key_passwd, out octetstring p_signature, out octetstring p_digest, out charstring p_x509_certificate_subject, out charstring p_x509_certificate_pem, out charstring p_pull_request_canonicalized) return integer; /** * @desc Verify signature -- GitLab From ce2d8daa6ae66f63aa312e49d797beeb71507b27 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Wed, 15 Mar 2023 13:10:28 +0100 Subject: [PATCH 15/37] Adapt ASN.1 files to TITAN requirements --- ccsrc/security/src/securty_services.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ccsrc/security/src/securty_services.cc b/ccsrc/security/src/securty_services.cc index aded5e9..a439a13 100644 --- a/ccsrc/security/src/securty_services.cc +++ b/ccsrc/security/src/securty_services.cc @@ -22,7 +22,7 @@ int security_services::initialize(const std::string& p_certs_db_path) { security_services::_certs_db = new certs_db(p_certs_db_path); if (security_services::_certs_db == nullptr) { // Memory allocation issue - loggers::get_instance().warning("security_services::setup: _security_db pointer is NULL"); + loggers::get_instance().warning("security_services::initialize: _security_db pointer is NULL"); return -1; } -- GitLab From 102e3b20c0d69ce260b02e1de3a446d0cba970e0 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Thu, 23 Mar 2023 09:44:59 +0100 Subject: [PATCH 16/37] Update templates with missing files --- ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn | 20 ++++++++++++++----- .../ttcn/LibHttp_XmlMessageBodyTypes.ttcn | 3 ++- ttcn/LibHttp/ttcn/LibHttp_XmlTemplates.ttcn | 2 ++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn b/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn index 08359cb..b5eb352 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn @@ -176,7 +176,9 @@ module LibHttp_Templates { statuscode := 200, statustext := "OK", header := p_header, - body := omit + body := omit, + tls := omit, + mutual_tls := omit } // End of template m_http_response_ok_no_body template (present) Response mw_http_response_ok_no_body( @@ -247,7 +249,9 @@ module LibHttp_Templates { statuscode := p_statuscode, statustext := p_statustext, header := p_header, - body := p_body + body := p_body, + tls := omit, + mutual_tls := omit } // End of template m_http_response_ko template (value) Response m_http_response_ko_no_body( @@ -260,7 +264,9 @@ module LibHttp_Templates { statuscode := p_statuscode, statustext := p_statustext, header := p_header, - body := omit + body := omit, + tls := omit, + mutual_tls := omit } // End of template m_http_response_ko_no_body template (value) Response m_http_response_500_internal_error( @@ -280,7 +286,9 @@ module LibHttp_Templates { statuscode := p_statuscode, statustext := p_statustext, header := p_header, - body := omit + body := omit, + tls := omit, + mutual_tls := omit } // End of template mw_http_response_ko_no_body template Response mw_http_response_ko( @@ -292,7 +300,9 @@ module LibHttp_Templates { statuscode := complement(200), statustext := ?, header := p_header, - body := p_body + body := p_body, + tls := omit, + mutual_tls := omit } // End of template mw_http_response_ko template (value) Response m_http_response_400_bad_request( diff --git a/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn b/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn index b82bee9..dbc3401 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn @@ -19,5 +19,6 @@ module LibHttp_XmlMessageBodyTypes { } } with { - variant "" + variant ""; + encode "XML" } // End of LibHttp_XmlMessageBodyTypes diff --git a/ttcn/LibHttp/ttcn/LibHttp_XmlTemplates.ttcn b/ttcn/LibHttp/ttcn/LibHttp_XmlTemplates.ttcn index fbfab3a..343300c 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_XmlTemplates.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_XmlTemplates.ttcn @@ -21,12 +21,14 @@ module LibHttp_XmlTemplates { template (value) XmlBody m_xml_body_raw( in template (value) charstring p_raw ) := { + msg := { raw := p_raw }, raw := p_raw } // End of template m_xml_body_raw template (present) XmlBody mw_xml_body_raw( template (present) charstring p_raw := ? ) := { + msg := { raw := p_raw }, raw := p_raw } // End of template mw_xml_body_raw -- GitLab From 59ef19049f80930a9c95f29e046ef69ab0b2199b Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Thu, 23 Mar 2023 18:19:18 +0100 Subject: [PATCH 17/37] Bug fixed in signature check --- ccsrc/Helpers/helpers_externals.cc | 62 ++++- ccsrc/Protocols/Xml/include/xml_converters.hh | 1 + ccsrc/Protocols/Xml/src/xml_converters.cc | 72 +++++- ccsrc/security/include/security_services.hh | 4 +- ccsrc/security/src/security_externals.cc | 129 +++++++++- ccsrc/security/src/securty_services.cc | 233 ++++++++++++------ ttcn/LibHelpers/module.mk | 1 - .../LibHelpers/ttcn/LibHelpers_Functions.ttcn | 8 + .../ttcn/LibHttp_XmlMessageBodyTypes.ttcn | 1 + ttcn/LibSecurity/module.mk | 5 +- .../ttcn/LibSecurity_Signature.ttcn | 26 +- .../ttcn/http_www_w3_org_2000_09_xmldsig.ttcn | 110 +++++++++ 12 files changed, 562 insertions(+), 90 deletions(-) create mode 100644 ttcn/LibSecurity/ttcn/http_www_w3_org_2000_09_xmldsig.ttcn diff --git a/ccsrc/Helpers/helpers_externals.cc b/ccsrc/Helpers/helpers_externals.cc index fd75828..d4dfde6 100644 --- a/ccsrc/Helpers/helpers_externals.cc +++ b/ccsrc/Helpers/helpers_externals.cc @@ -1,9 +1,14 @@ -#include "LibHelpers_Functions.hh" #include +#include +#include +#include + +#include "LibHelpers_Functions.hh" #include "base_time.hh" #include "converter.hh" #include "loggers.hh" +#include "xml_converters.hh" #ifndef M_PI #define M_PI 3.14159265358979323846 @@ -74,4 +79,59 @@ namespace LibHelpers__Functions { return os; } + static unsigned char random_char() { + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(0, 255); + return static_cast(dis(gen)); + } + + static std::string generate_hex(const unsigned int len) { + std::stringstream ss; + for(auto i = 0; i < len; i++) { + auto rc = random_char(); + std::stringstream hexstream; + hexstream << std::hex << int(rc); + auto hex = hexstream.str(); + ss << (hex.length() < 2 ? '0' + hex : hex); + } + return ss.str(); + } + + /** + * @brief Generate a new UUID + * @return The UUID in string format on success, a null string otherwise + */ + CHARSTRING fx__generate__uuid() { // ddb848c4-f7fd-445f-bdc8-033d15d7c528 + loggers::get_instance().log(">>> fx__generate__uuid"); + + std::stringstream ss; + ss << generate_hex(6) << "-"; + ss << generate_hex(2) << "-"; + ss << generate_hex(2) << "-"; + ss << generate_hex(2) << "-"; + ss << generate_hex(6); + + CHARSTRING uuid(ss.str().c_str()); + loggers::get_instance().log_msg("fx__generate__uuid: ", uuid); + return uuid; + } + + /** + * @brief Retrieve the current local date/time formatted as yyyy-mm-ddThh:mm:ss.lll+nn:00 + * @return The the current date/time on success, a null string otherwise + */ + CHARSTRING fx__get__current__date__time() { //2018-01-18T13:19:35.367+01:00 + loggers::get_instance().log(">>> fx__get__current__date__time"); + + time_t t = std::time(nullptr); + auto tm = *std::localtime(&t); + std::ostringstream oss; + oss << std::put_time(&tm, "%FT%T");//%FT%T%Z + + CHARSTRING dt(oss.str().c_str()); + loggers::get_instance().log_msg("fx__get__current__date__time: ", dt); + return dt; + } + } // namespace LibHelpers__Functions diff --git a/ccsrc/Protocols/Xml/include/xml_converters.hh b/ccsrc/Protocols/Xml/include/xml_converters.hh index 9771074..ed15995 100644 --- a/ccsrc/Protocols/Xml/include/xml_converters.hh +++ b/ccsrc/Protocols/Xml/include/xml_converters.hh @@ -35,6 +35,7 @@ public: public: int xml_canonicalization(const std::string& p_to_canonical, std::string& p_canonicalized) const; + int xml_transform(const std::string& p_to_transform, std::string& p_transformed) const; }; // End of class xml_converters diff --git a/ccsrc/Protocols/Xml/src/xml_converters.cc b/ccsrc/Protocols/Xml/src/xml_converters.cc index aebace2..989e62e 100644 --- a/ccsrc/Protocols/Xml/src/xml_converters.cc +++ b/ccsrc/Protocols/Xml/src/xml_converters.cc @@ -14,9 +14,77 @@ #include #include +#include +#include +#include +#include xml_converters* xml_converters::_instance = nullptr; +// FIXME Use libxslt +int xml_converters::xml_transform(const std::string& p_to_transform, std::string& p_transformed) const { + loggers::get_instance().log(">>> xml_converters::xml_transform: '%s'", p_to_transform.c_str()); + + + xmlDocPtr doc = xmlReadMemory(p_to_transform.c_str(), p_to_transform.length(), "noname.xml", NULL, 0); + xmlChar *xmlbuff; + int buffersize; + xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1); + loggers::get_instance().log("xml_converters::xml_transform: tree dump: '%s'", (char *) xmlbuff); + //"\\n\\t\\n\\t\\t\\n\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\t\\n\\t\\t\\n\\t\\n\\t" + + //xsltApplyStylesheet(cur, doc, params); + xmlFree(xmlbuff); + xmlFreeDoc(doc); + + + int first = p_to_transform.find('>'); + int next = 0; + while ((first != -1) && (first < p_to_transform.length())) { + //loggers::get_instance().log("xml_converters::xml_transform: first: '%d'", first); + //loggers::get_instance().log("xml_converters::xml_transform: next: '%d'", next); + p_transformed += p_to_transform.substr(next, first - next + 1); + //loggers::get_instance().log("xml_converters::xml_transform: p_to_transform: '%s'", p_to_transform.c_str()); + //loggers::get_instance().log("xml_converters::xml_transform: p_transformed: '%s'", p_transformed.c_str()); + next = first + 1; + while ( + (p_to_transform[next] == '\r') || + (p_to_transform[next] == '\n') || + (p_to_transform[next] == '\t') || + (p_to_transform[next] == ' ') + ) { // Skip CR, LF, TAG and SPACE + next += 1; + } // End of 'while'statement + first = p_to_transform.find('>', next); + } // End of 'while'statement + + // + first = p_transformed.find("ns4:"); + while ((first != -1) && (first < p_to_transform.length())) { + p_transformed = p_transformed.substr(0, first) + p_transformed.substr(first + 4, p_transformed.length() - 4 - 1); + loggers::get_instance().log("xml_converters::xml_transform: New p_transformed (1): '%s'", p_transformed.c_str()); + first = p_transformed.find("ns4:"); + } // End of 'while'statement + + first = p_transformed.find("xmlns:ns4"); + while ((first != -1) && (first < p_to_transform.length())) { + next = p_transformed.find("\">", first + 1); + p_transformed = p_transformed.substr(0, first - 1) + p_transformed.substr(next + 1, p_transformed.length() - next - 1); + loggers::get_instance().log("xml_converters::xml_transform: New p_transformed (2): '%s'", p_transformed.c_str()); + first = p_transformed.find("xmlns:ns4"); + } // End of 'while'statement + + // + first = p_transformed.find("", first + 8 + 1); + p_transformed = p_transformed.substr(0, first + 8) + p_transformed.substr(next + 1, p_transformed.length() - next - 1); + } + + loggers::get_instance().log("<<< xml_converters::xml_transform: '%s'", p_transformed.c_str()); + return 0; +} + int xml_converters::xml_canonicalization(const std::string& p_to_canonical, std::string& p_canonicalized) const { loggers::get_instance().log(">>> xml_converters::xml_canonicalization: '%s'", p_to_canonical.c_str()); @@ -34,14 +102,12 @@ int xml_converters::xml_canonicalization(const std::string& p_to_canonical, std: } // Do canonicalization - loggers::get_instance().log("xml_converters::xml_canonicalization: Before"); - if (xmlC14NExecute(doc, (xmlC14NIsVisibleCallback)&xml_converters::xml_node_set_contains_callback, nullptr, XML_C14N_1_1, nullptr, 1, buffer) == -1) { + if (xmlC14NExecute(doc, nullptr/*(xmlC14NIsVisibleCallback)&xml_converters::xml_node_set_contains_callback*/, nullptr, XML_C14N_EXCLUSIVE_1_0, nullptr, 1, buffer) == -1) { loggers::get_instance().log("xml_converters::xml_canonicalization: Failed to read XML input"); xmlFreeDoc(doc); xmlOutputBufferClose(buffer); return -1; } - loggers::get_instance().log("xml_converters::xml_canonicalization: After"); // Retrieve the canonicalization XML document const char* data = (const char*)xmlOutputBufferGetContent(buffer); diff --git a/ccsrc/security/include/security_services.hh b/ccsrc/security/include/security_services.hh index 9c28a4d..7c32f05 100644 --- a/ccsrc/security/include/security_services.hh +++ b/ccsrc/security/include/security_services.hh @@ -48,7 +48,7 @@ public: /*! \publicsection */ * \param[in] TODO The raw message to be signed * \return 0 on success, -1 otherwise */ - int do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_canonicalized); + int do_sign(const OCTETSTRING& p_encoded_message, const OCTETSTRING& p_empty_signature, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_canonicalized); /*! * \fn int build_path(const std::string& p_root_directory); * \brief Verify message signature @@ -56,5 +56,5 @@ public: /*! \publicsection */ * \param[in] TODO * \return true on success, false otherwise */ - bool do_sign_verify(const CHARSTRING& p_message, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate, const CHARSTRING& p_debug_message); + bool do_sign_verify(const CHARSTRING& p_message, const OCTETSTRING& p_empty_signature, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate, CHARSTRING& p_debug_message); }; \ No newline at end of file diff --git a/ccsrc/security/src/security_externals.cc b/ccsrc/security/src/security_externals.cc index c8ec692..e129ea7 100644 --- a/ccsrc/security/src/security_externals.cc +++ b/ccsrc/security/src/security_externals.cc @@ -12,6 +12,66 @@ static std::unique_ptr _security_services; +static int transform_signature_workaround(std::string& str) { + loggers::get_instance().log(">>> transform_signature_workaround: '%s'", str.c_str()); + int first = str.find("<"); + while ((first != -1) && (first < str.length())) { + str = str.substr(0, first) + "<" + str.substr(first + 4, str.length() - 4); + //loggers::get_instance().log("transform_signature_workaround: New str (1): '%s'", str.c_str()); + first = str.find("<"); + } // End of 'while'statement + first = str.find(">"); + while ((first != -1) && (first < str.length())) { + str = str.substr(0, first) + ">" + str.substr(first + 4, str.length() - 4); + //loggers::get_instance().log("transform_signature_workaround: New str (2): '%s'", str.c_str()); + first = str.find(">"); + } // End of 'while'statement + first = str.find("""); + while ((first != -1) && (first < str.length())) { + str = str.substr(0, first) + "'" + str.substr(first + 6, str.length() - 6); + //loggers::get_instance().log("transform_signature_workaround: New str (3): '%s'", str.c_str()); + first = str.find("""); + } // End of 'while'statement + + std::replace(str.begin(), str.end(), '\'', '\"'); + + loggers::get_instance().log("<<< transform_signature_workaround: '%s'", str.c_str()); + return 0; +} + +static int transform_xslt_workaround(std::string& str) { + loggers::get_instance().log(">>> transform_xslt_workaround: '%s'", str.c_str()); + + int start = str.find(""); + //loggers::get_instance().log("transform_xslt_workaround: stop='%d' ", stop); + int first = str.find("<", start); + while ((first != -1) && (first < stop)) { + //loggers::get_instance().log("transform_xslt_workaround: first='%d' ", first); + str = str.substr(0, first - 1) + "<" + str.substr(first + 1, str.length() - 1); + //loggers::get_instance().log("transform_xslt_workaround: New str (1): '%s'", str.c_str()); + first = str.find("<", first); + } // End of 'while'statement + first = str.find(">", start); + while ((first != -1) && (first < stop)) { + //loggers::get_instance().log("transform_xslt_workaround: first='%d' ", first); + str = str.substr(0, first - 1) + ">" + str.substr(first + 1, str.length() - 1); + //loggers::get_instance().log("transform_xslt_workaround: New str (1): '%s'", str.c_str()); + first = str.find(">", first); + } // End of 'while'statement + first = str.find("\"", start); + while ((first != -1) && (first < stop)) { + //loggers::get_instance().log("transform_xslt_workaround: first='%d' ", first); + str = str.substr(0, first - 1) + """ + str.substr(first + 1, str.length() - 1); + //loggers::get_instance().log("transform_xslt_workaround: New str (1): '%s'", str.c_str()); + first = str.find("\"", first); + } // End of 'while'statement + + loggers::get_instance().log("<<< transform_xslt_workaround: '%s'", str.c_str()); + return 0; +} + INTEGER LibSecurity__Certificates::fx__init__certs__db(const CHARSTRING& p_certs_db_path) { loggers::get_instance().log_msg(">>> fx__init__certs__db: ", p_certs_db_path); @@ -69,10 +129,70 @@ OCTETSTRING LibSecurity__Hash::fx__hash(const OCTETSTRING& p_to_be_hashed, const return hash; } -INTEGER LibSecurity__Signature::fx__sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_canonicalized) { +OCTETSTRING LibSecurity__Signature::fx__enc__xmldsig__signed__info(const http__www__w3__org__2000__09__xmldsig::Signature_signedInfo& s) { // FIXME Use enc/dec TITAN function external function f_enc_value(in Value x) return bitstring with { extension "prototype(convert) encode(abc)" } + loggers::get_instance().log(">>> fx__enc__xmldsig__signed__info"); + + TTCN_EncDec::clear_error(); + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT); + TTCN_Buffer encoding_buffer; + + s.encode(http__www__w3__org__2000__09__xmldsig::Signature_signedInfo_descr_, encoding_buffer, TTCN_EncDec::CT_XER, XER_EXTENDED); + + // FIXME Update + std::string str(static_cast((const char*)encoding_buffer.get_data()), encoding_buffer.get_len() + static_cast((const char*)encoding_buffer.get_data())); + loggers::get_instance().log("fx__enc__xmldsig__signed__info: Before str: '%s'", str.c_str()); + transform_signature_workaround(str); + loggers::get_instance().log("fx__enc__xmldsig__signed__info: Afer str: '%s'", str.c_str()); + + OCTETSTRING os = char2oct(CHARSTRING(str.c_str())); + loggers::get_instance().log_msg("fx__enc__xmldsig__signed__info: os: ", os); + + return os; +} + +OCTETSTRING LibSecurity__Signature::fx__enc__xmldsig(const http__www__w3__org__2000__09__xmldsig::Signature& s) { // FIXME Use enc/dec TITAN function external function f_enc_value(in Value x) return bitstring with { extension "prototype(convert) encode(abc)" } + loggers::get_instance().log(">>> fx__enc__xmldsig"); + + TTCN_EncDec::clear_error(); + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT); + TTCN_Buffer encoding_buffer; + + s.encode(http__www__w3__org__2000__09__xmldsig::Signature_descr_, encoding_buffer, TTCN_EncDec::CT_XER, XER_EXTENDED); + + // FIXME Update + std::string str(static_cast((const char*)encoding_buffer.get_data()), encoding_buffer.get_len() + static_cast((const char*)encoding_buffer.get_data())); + loggers::get_instance().log("fx__enc__xmldsig: Before str: '%s'", str.c_str()); + transform_signature_workaround(str); + loggers::get_instance().log("fx__enc__xmldsig: Afer str: '%s'", str.c_str()); + + OCTETSTRING os = char2oct(CHARSTRING(str.c_str())); + loggers::get_instance().log_msg("fx__enc__xmldsig: os: ", os); + + return os; +} + +INTEGER LibSecurity__Signature::fx__dec__xmldsig(const BITSTRING& bs, http__www__w3__org__2000__09__xmldsig::Signature& s) { // FIXME Use enc/dec TITAN function external function f_enc_value(in Value x) return bitstring with { extension "prototype(convert) encode(abc)" } + loggers::get_instance().log(">>> fx__dec__xmldsig"); + + std::string str(static_cast(oct2char(bit2oct(bs)))); + loggers::get_instance().log("fx__dec__xmldsig: Before str: '%s'", str.c_str()); + transform_xslt_workaround(str); + loggers::get_instance().log("fx__dec__xmldsig: Afer str: '%s'", str.c_str()); + + TTCN_EncDec::clear_error(); + TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT); + TTCN_Buffer decoding_buffer(OCTETSTRING(str.length(), (const unsigned char*)str.c_str())); + + s.decode(http__www__w3__org__2000__09__xmldsig::Signature_descr_, decoding_buffer, TTCN_EncDec::CT_XER, XER_EXTENDED); + + loggers::get_instance().log_msg("<<< fx__dec__xmldsig: ", s); + return 0; +} + +INTEGER LibSecurity__Signature::fx__sign(const OCTETSTRING& p_encoded_message, const OCTETSTRING& p_empty_signature, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_canonicalized) { loggers::get_instance().log_msg(">>> fx__sign: ", p_encoded_message); - if (_security_services->do_sign(p_encoded_message, p_certificate_name, p_private_key_name, p_private_key_passwd, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem, p_pull_request_canonicalized) == -1) { + if (_security_services->do_sign(p_encoded_message, p_empty_signature, p_certificate_name, p_private_key_name, p_private_key_passwd, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem, p_pull_request_canonicalized) == -1) { loggers::get_instance().log("fx__sign: Failed to signed message"); return -1; } @@ -80,14 +200,13 @@ INTEGER LibSecurity__Signature::fx__sign(const OCTETSTRING& p_encoded_message, c return 0; } -BOOLEAN LibSecurity__Signature::fx__do__sign__verify(const CHARSTRING& p_message, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate, const CHARSTRING& p_debug_message) { +BOOLEAN LibSecurity__Signature::fx__do__sign__verify(const CHARSTRING& p_message, const OCTETSTRING& p_empty_signature, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate, CHARSTRING& p_debug_message) { loggers::get_instance().log(">>> fx__do__sign__verify"); - if (!_security_services->do_sign_verify(p_message, p_canonicalization_method, p_signature_method, p_digest_method, p_digest_value, p_signature_value, p_subject_name, p_certificate, p_debug_message)) { + if (!_security_services->do_sign_verify(p_message, p_empty_signature, p_canonicalization_method, p_signature_method, p_digest_method, p_digest_value, p_signature_value, p_subject_name, p_certificate, p_debug_message)) { loggers::get_instance().log("fx__do__sign__verify: Failed to verify message signature"); return false; } return true; } - \ No newline at end of file diff --git a/ccsrc/security/src/securty_services.cc b/ccsrc/security/src/securty_services.cc index 7562e4e..73423f2 100644 --- a/ccsrc/security/src/securty_services.cc +++ b/ccsrc/security/src/securty_services.cc @@ -12,6 +12,7 @@ #include "sha1.hh" #include "sha256.hh" +#include "sha384.hh" #include "certs_loader.hh" #include "security_services.hh" @@ -38,19 +39,68 @@ int security_services::load_certificate(const std::string& p_certificate_name, c return _certs_db->get_certificate(p_certificate_name, p_private_key_name, p_private_key_passwd, p_certificate); } -int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_canonicalized) { +int security_services::do_sign(const OCTETSTRING& p_encoded_message, const OCTETSTRING& p_empty_signature, const CHARSTRING& p_certificate_name, const CHARSTRING& p_private_key_name, const CHARSTRING& p_private_key_passwd, OCTETSTRING& p_signature, OCTETSTRING& p_digest, CHARSTRING& p_x509_certificate_subject, CHARSTRING& p_x509_certificate_pem, CHARSTRING& p_pull_request_canonicalized) { loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_encoded_message); + loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_empty_signature); loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_certificate_name); loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_private_key_name); loggers::get_instance().log_msg(">>> security_services::do_sign: ", p_private_key_passwd); + // Transform and canonicalize the message + // Transform: Remove all CR, LS, TAB and SPACE outside of the tags + std::string transformed; + xml_converters::get_instance().xml_transform(std::string((const char*)(static_cast(p_encoded_message)), p_encoded_message.lengthof()), transformed); + loggers::get_instance().log("security_services::do_sign: p_pull_request_transormed: ", transformed.c_str()); // Canonicalization std::string canonicalized; - xml_converters::get_instance().xml_canonicalization(std::string((const char*)(static_cast(p_encoded_message)), p_encoded_message.lengthof()), canonicalized); + xml_converters::get_instance().xml_canonicalization(transformed, canonicalized); p_pull_request_canonicalized = CHARSTRING(canonicalized.c_str()); OCTETSTRING encoded_message(char2oct(p_pull_request_canonicalized)); loggers::get_instance().log_msg("security_services::do_sign: p_pull_request_canonicalized: ", p_pull_request_canonicalized); + // Transform and canonicalize the empty signature + // Transform: Remove all CR, LS, TAB and SPACE outside of the tags + transformed.clear(); + xml_converters::get_instance().xml_transform(std::string((const char*)(static_cast(p_empty_signature)), p_empty_signature.lengthof()), transformed); + loggers::get_instance().log("security_services::do_sign: p_empty_signature transormed: '%s'", transformed.c_str()); + // Canonicalization + canonicalized.clear(); + xml_converters::get_instance().xml_canonicalization(transformed, canonicalized); + loggers::get_instance().log("security_services::do_sign: p_empty_signature canonicalized: '%s'", canonicalized.c_str()); + + // Compute the digest of the transformed/canonicalized message + loggers::get_instance().log_msg("security_services::do_sign: compute digest for ", p_pull_request_canonicalized); + int first = canonicalized.find("xmldsig#sha1"); + loggers::get_instance().log("security_services::do_sign: p_empty_signature first: '%d'", first); + const EVP_MD* sign_digest; + if (first != -1) { + sha1 digest; + digest.generate(char2oct(p_pull_request_canonicalized), p_digest); + sign_digest = EVP_sha1(); + } else { + first = canonicalized.find("xmldsig#sha256"); + loggers::get_instance().log("security_services::do_sign: p_empty_signature first: '%d'", first); + if (first != -1) { + sha256 digest; + digest.generate(char2oct(p_pull_request_canonicalized), p_digest); + sign_digest = EVP_sha256(); + } else { + first = canonicalized.find("xmldsig#sha384"); + loggers::get_instance().log("security_services::do_sign: p_empty_signature first: '%d'", first); + if (first != -1) { + sha384 digest; + digest.generate(char2oct(p_pull_request_canonicalized), p_digest); + sign_digest = EVP_sha384(); + } else { + loggers::get_instance().error("security_services::do_sign: Unsupported digest"); + } + } + } + loggers::get_instance().log_msg("security_services::do_sign: digest: ", p_digest); + std::vector to64 = converter::get_instance().buffer_to_base64(std::vector(static_cast(p_digest), p_digest.lengthof() + static_cast(p_digest))); + p_digest = OCTETSTRING(to64.size(), to64.data()); + loggers::get_instance().log_msg("security_services::do_sign: digest (64): ", p_digest); + // Retrieve certificate std::string certificate_id; if (certs_loader::get_instance().get_certificate_id(std::string(static_cast(p_certificate_name)), certificate_id) != 0) { @@ -77,10 +127,11 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARS } p_x509_certificate_pem = CHARSTRING(str.c_str()); - // Compute the digest - sha256 digest; - digest.generate(char2oct(CHARSTRING(canonicalized.c_str())), p_digest); - loggers::get_instance().log_msg("security_services::do_sign: digest: ", p_digest); + // Update the signature + int i = canonicalized.find(""); + canonicalized = canonicalized.substr(0, i + 13) + std::string(to64.cbegin(), to64.cend()) + canonicalized.substr(i + 13, canonicalized.length() - i - 13); + OCTETSTRING to_be_signed(char2oct(CHARSTRING(canonicalized.c_str()))); + loggers::get_instance().log_msg("security_services::do_sign: to_be_signed: ", to_be_signed); // Retrive the private key const EVP_PKEY* private_key; @@ -91,13 +142,13 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARS } loggers::get_instance().log("security_services::do_sign: private_key: '%p'", private_key); - // Create signing context + // Create signing context to sign the updated signature EVP_MD_CTX* ctx = ::EVP_MD_CTX_new(); if (ctx == NULL) { loggers::get_instance().warning("security_services::do_sign: EVP_MD_CTX_create failed, error 0x%lx", ::ERR_get_error()); return -1; } - if (::EVP_DigestSignInit(ctx, NULL, EVP_sha256(), NULL, (EVP_PKEY*)private_key) != 1) { // FIXME Add parameter to chose the digest algorithm + if (::EVP_DigestSignInit(ctx, NULL, sign_digest, NULL, (EVP_PKEY*)private_key) != 1) { // FIXME Add parameter to chose the digest algorithm loggers::get_instance().warning("security_services::do_sign: EVP_DigestSignInit failed, error 0x%lx", ::ERR_get_error()); ::EVP_MD_CTX_free(ctx); return -1; @@ -129,47 +180,101 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const CHARS } ::EVP_MD_CTX_free(ctx); - // Ensure that the signature round-trips - // Retrive the public key - const EVP_PKEY* public_key; - if (_certs_db->get_private_key(certificate_id, &public_key) == 1) { - loggers::get_instance().warning("security_services::do_sign: Failed to retrieve private key"); - return -1; - } - loggers::get_instance().log("security_services::do_sign: public_key: '%p'", public_key); - std::vector buffer; - _certs_db->publickey_to_string(public_key, buffer); - ctx = ::EVP_MD_CTX_new(); - if (!::EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, (EVP_PKEY*)public_key) || - !::EVP_DigestVerifyUpdate(ctx, (const unsigned char*)canonicalized.c_str(), canonicalized.length()) || - !::EVP_DigestVerifyFinal(ctx, s.data(), s.size())) { - loggers::get_instance().warning("security_services::do_sign: Failed to verify signature, error 0x%lx", ::ERR_get_error()); - ::EVP_MD_CTX_free(ctx); - s.clear(); - return -1; - } - ::EVP_MD_CTX_free(ctx); - loggers::get_instance().log("security_services::do_sign: signature was verified with public key"); + // // Ensure that the signature round-trips + // // Retrive the public key + // const EVP_PKEY* public_key; + // if (_certs_db->get_private_key(certificate_id, &public_key) == 1) { + // loggers::get_instance().warning("security_services::do_sign: Failed to retrieve private key"); + // return -1; + // } + // loggers::get_instance().log("security_services::do_sign: public_key: '%p'", public_key); + // std::vector buffer; + // _certs_db->publickey_to_string(public_key, buffer); + // ctx = ::EVP_MD_CTX_new(); + // if (!::EVP_DigestVerifyInit(ctx, NULL, sign_digest, NULL, (EVP_PKEY*)public_key) || + // !::EVP_DigestVerifyUpdate(ctx, (const unsigned char*)canonicalized.c_str(), canonicalized.length()) || + // !::EVP_DigestVerifyFinal(ctx, s.data(), s.size())) { + // loggers::get_instance().warning("security_services::do_sign: Failed to verify signature, error 0x%lx", ::ERR_get_error()); + // ::EVP_MD_CTX_free(ctx); + // s.clear(); + // return -1; + // } + //::EVP_MD_CTX_free(ctx); + //loggers::get_instance().log("security_services::do_sign: signature was verified with public key"); p_signature = OCTETSTRING(signature_length, s.data()); + loggers::get_instance().log_msg("security_services::do_sign: signature: ", p_signature); + to64 = converter::get_instance().buffer_to_base64(std::vector(static_cast(p_signature), p_signature.lengthof() + static_cast(p_signature))); + p_signature = OCTETSTRING(to64.size(), to64.data()); + loggers::get_instance().log_msg("security_services::do_sign: signature (64): ", p_signature); loggers::get_instance().log_msg("<<< security_services::do_sign: signature: ", p_signature); return 0; } -bool security_services::do_sign_verify(const CHARSTRING& p_message, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate, const CHARSTRING& p_debug_message) { +bool security_services::do_sign_verify(const CHARSTRING& p_message, const OCTETSTRING& p_empty_signature, const UNIVERSAL_CHARSTRING& p_canonicalization_method, const UNIVERSAL_CHARSTRING& p_signature_method, const UNIVERSAL_CHARSTRING& p_digest_method, const UNIVERSAL_CHARSTRING& p_digest_value, const UNIVERSAL_CHARSTRING& p_signature_value, const UNIVERSAL_CHARSTRING& p_subject_name, const UNIVERSAL_CHARSTRING& p_certificate, CHARSTRING& p_debug_message) { loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_message: ", p_message); loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_debug_message: ", p_debug_message); loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_canonicalization_method: ", p_canonicalization_method); loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_subject_name: ", p_subject_name); loggers::get_instance().log_msg(">>> security_services::do_sign_verify: p_signature_method: ", p_signature_method); - // Compute the digest - sha256 digest; + // Transform and canonicalize the message + // Transform: Remove all CR, LS, TAB and SPACE outside of the tags + std::string transformed; + xml_converters::get_instance().xml_transform(std::string(static_cast(p_message)), transformed); + loggers::get_instance().log("security_services::do_sign_verify: p_message_transormed: ", transformed.c_str()); + // Canonicalization + std::string canonicalized; + xml_converters::get_instance().xml_canonicalization(transformed, canonicalized); + CHARSTRING v_pull_request_canonicalized(canonicalized.c_str()); + p_debug_message = v_pull_request_canonicalized; + //OCTETSTRING v_pull_request_canonicalized(char2oct(p_debug_message)); + loggers::get_instance().log_msg("security_services::do_sign_verify: p_debug_message: ", p_debug_message); + + // Transform and canonicalize the empty signature + // Transform: Remove all CR, LS, TAB and SPACE outside of the tags + transformed.clear(); + xml_converters::get_instance().xml_transform(std::string((const char*)(static_cast(p_empty_signature)), p_empty_signature.lengthof()), transformed); + loggers::get_instance().log("security_services::do_sign: p_empty_signature transormed: '%s'", transformed.c_str()); + // Canonicalization + canonicalized.clear(); + xml_converters::get_instance().xml_canonicalization(transformed, canonicalized); + loggers::get_instance().log("security_services::do_sign: p_empty_signature canonicalized: '%s'", canonicalized.c_str()); + + // Compute the digest of the transformed/canonicalized message + loggers::get_instance().log_msg("security_services::do_sign: compute digest for ", v_pull_request_canonicalized); + int first = canonicalized.find("xmldsig#sha1"); + loggers::get_instance().log("security_services::do_sign: p_empty_signature first: '%d'", first); OCTETSTRING dg; - digest.generate(char2oct(p_message), dg); + const EVP_MD* sign_digest; + if (first != -1) { + sha1 digest; + digest.generate(char2oct(v_pull_request_canonicalized), dg); + sign_digest = EVP_sha1(); + } else { + first = canonicalized.find("xmldsig#sha256"); + loggers::get_instance().log("security_services::do_sign_verify: p_empty_signature first: '%d'", first); + if (first != -1) { + sha256 digest; + digest.generate(char2oct(v_pull_request_canonicalized), dg); + sign_digest = EVP_sha256(); + } else { + first = canonicalized.find("xmldsig#sha384"); + loggers::get_instance().log("security_services::do_sign_verify: p_empty_signature first: '%d'", first); + if (first != -1) { + sha384 digest; + digest.generate(char2oct(v_pull_request_canonicalized), dg); + sign_digest = EVP_sha384(); + } else { + loggers::get_instance().error("security_services::do_sign_verify: Unsupported digest"); + } + } + } loggers::get_instance().log_msg("security_services::do_sign_verify: digest: ", dg); + std::vector to64 = converter::get_instance().buffer_to_base64(std::vector(static_cast(dg), dg.lengthof() + static_cast(dg))); + loggers::get_instance().log_msg("security_services::do_sign_verify: digest (64): ", OCTETSTRING(to64.size(), to64.data())); // Retrieve certificate std::string sn(static_cast(unichar2char(p_subject_name))); @@ -213,38 +318,13 @@ bool security_services::do_sign_verify(const CHARSTRING& p_message, const UNIVER std::vector buffer; _certs_db->publickey_to_string(public_key, buffer); - // Create signing context - EVP_MD_CTX* ctx = ::EVP_MD_CTX_new(); - if (ctx == NULL) { - loggers::get_instance().warning("security_services::do_sign_verify: EVP_MD_CTX_create failed, error 0x%lx", ::ERR_get_error()); - return false; - } - std::string signature_method(static_cast(unichar2char(p_signature_method))); // E.g. http://www.w3.org/2000/09/xmldsig#rsa-sha1 - const EVP_MD *md; - if (signature_method.find("sha1") != std::string::npos) { - loggers::get_instance().log("security_services::do_sign_verify: signature method: sha1"); - md = EVP_sha1(); - } else if (signature_method.find("sha256") != std::string::npos) { - loggers::get_instance().log("security_services::do_sign_verify: signature method: sha256"); - md = EVP_sha256(); - } else if (signature_method.find("sha384") != std::string::npos) { - loggers::get_instance().log("security_services::do_sign_verify: signature method: sha384"); - md = EVP_sha384(); - } else { - loggers::get_instance().error("security_services::do_sign_verify: Unsupported signature method"); - return false; - } - // Check signature - if (::EVP_DigestVerifyInit(ctx, NULL, md, NULL, (EVP_PKEY*)public_key) != 1) { - loggers::get_instance().warning("security_services::do_sign_verify: EVP_DigestVerifyInit failed, error 0x%lx", ::ERR_get_error()); - ::EVP_MD_CTX_free(ctx); - return false; - } - if(::EVP_DigestVerifyUpdate(ctx, (const char*)p_message, p_message.lengthof()) != 1) { - loggers::get_instance().warning("security_services::do_sign_verify: EVP_DigestVerifyUpdate failed, error 0x%lx - %s", ::ERR_get_error(), ::ERR_error_string(::ERR_get_error(), nullptr)); - ::EVP_MD_CTX_free(ctx); - return false; - } + // Update the DigestValue + int i = canonicalized.find(""); + canonicalized = canonicalized.substr(0, i + 13) + std::string(to64.cbegin(), to64.cend()) + canonicalized.substr(i + 13, canonicalized.length() - i - 13); + OCTETSTRING to_be_signed(char2oct(CHARSTRING(canonicalized.c_str()))); + loggers::get_instance().log_msg("security_services::do_sign: to_be_signed: ", to_be_signed); + + // Convert signature std::string signature_value(static_cast(unichar2char(p_signature_value))); // Remove CR/LF if any //signature_value.erase(std::remove(signature_value.begin(), signature_value.end(), '\r'), signature_value.end()); @@ -252,16 +332,27 @@ bool security_services::do_sign_verify(const CHARSTRING& p_message, const UNIVER loggers::get_instance().log("security_services::do_sign_verify: Before B64 decoded: '%s'", signature_value.c_str()); // Convert into bytes buffer const std::vector to_decode((const unsigned char*)signature_value.c_str(), static_cast((const unsigned char*)signature_value.c_str() + signature_value.length())); - std::vector b64 = converter::get_instance().base64_to_buffer(to_decode); - loggers::get_instance().log("security_services::do_sign_verify: B64 decoded: '%s'", converter::get_instance().bytes_to_hexa(b64, true).c_str()); - loggers::get_instance().log("security_services::do_sign_verify: B64 decoded len: '%d'", b64.size()); - if(::EVP_DigestVerifyFinal(ctx, b64.data(), b64.size()) != 1) { - loggers::get_instance().warning("security_services::do_sign_verify: EVP_DigestVerifyFinal failed, error 0x%lx - %s", ::ERR_get_error(), ::ERR_error_string(::ERR_get_error(), nullptr)); + std::vector s = converter::get_instance().base64_to_buffer(to_decode); + loggers::get_instance().log("security_services::do_sign_verify: B64 decoded: '%s'", converter::get_instance().bytes_to_hexa(s, true).c_str()); + loggers::get_instance().log("security_services::do_sign_verify: B64 decoded len: '%d'", s.size()); + + // Create signing context + EVP_MD_CTX* ctx = ::EVP_MD_CTX_new(); + if (ctx == NULL) { + loggers::get_instance().warning("security_services::do_sign_verify: EVP_MD_CTX_create failed, error 0x%lx", ::ERR_get_error()); + return false; + } + // Check signature + if (!::EVP_DigestVerifyInit(ctx, NULL, sign_digest, NULL, (EVP_PKEY*)public_key) || + !::EVP_DigestVerifyUpdate(ctx, (const unsigned char*)canonicalized.c_str(), canonicalized.length()) || + !::EVP_DigestVerifyFinal(ctx, s.data(), s.size())) { + loggers::get_instance().warning("security_services::do_sign_verify: Failed to verify signature, error 0x%lx", ::ERR_get_error()); ::EVP_MD_CTX_free(ctx); + s.clear(); return false; } - ::EVP_MD_CTX_free(ctx); + loggers::get_instance().log("security_services::do_sign_verify: signature was verified with public key"); return true; } diff --git a/ttcn/LibHelpers/module.mk b/ttcn/LibHelpers/module.mk index f56baa1..3012e9e 100644 --- a/ttcn/LibHelpers/module.mk +++ b/ttcn/LibHelpers/module.mk @@ -1,3 +1,2 @@ sources := \ ttcn/LibHelpers_Functions.ttcn - diff --git a/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn b/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn index e0f9967..f7edf96 100644 --- a/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn +++ b/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn @@ -172,6 +172,14 @@ module LibHelpers_Functions { */ external function fx_dec_base64(in octetstring p_to_decode) return octetstring; + /** + * @desc Generate a new UUID + * @return The UUID in string format on success, a null string otherwise + */ + external function fx_generate_uuid() return charstring; + + external function fx_get_current_date_time() return charstring; + } // End of externals } // End of module LibHelpers_Functions diff --git a/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn b/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn index b82bee9..96cfb2f 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn @@ -19,5 +19,6 @@ module LibHttp_XmlMessageBodyTypes { } } with { + encode "XML"; variant "" } // End of LibHttp_XmlMessageBodyTypes diff --git a/ttcn/LibSecurity/module.mk b/ttcn/LibSecurity/module.mk index 4514de4..79a47a2 100644 --- a/ttcn/LibSecurity/module.mk +++ b/ttcn/LibSecurity/module.mk @@ -2,4 +2,7 @@ sources := \ ttcn/LibSecurity_Hash.ttcn \ ttcn/LibSecurity_Hmac.ttcn \ ttcn/LibSecurity_Signature.ttcn \ - ttcn/LibSecurity_Certificates.ttcn + ttcn/LibSecurity_Certificates.ttcn \ + ttcn/http_www_w3_org_2000_09_xmldsig.ttcn \ + + diff --git a/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn b/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn index 74065a6..bf2b5e1 100644 --- a/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn +++ b/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn @@ -1,5 +1,17 @@ module LibSecurity_Signature { + import from http_www_w3_org_2000_09_xmldsig all; + + external function fx_enc_xmldsig_signed_info(in Signature.signedInfo s) return octetstring; // Use encvalue decoration + //external function fx_enc_PullRequest_1(in PullRequest p_pull_request) return bitstring with {extension "prototype(convert) encode(XML)"} + //external function fx_dec_PullRequest_1(inout bitstring b, out PullRequest p_pull_request)return integer with {extension "prototype(sliding) decode(XML)"} + + external function fx_enc_xmldsig(in Signature s) return octetstring; // Use encvalue decoration + //external function fx_enc_PullRequest_1(in PullRequest p_pull_request) return bitstring with {extension "prototype(convert) encode(XML)"} + //external function fx_dec_PullRequest_1(inout bitstring b, out PullRequest p_pull_request)return integer with {extension "prototype(sliding) decode(XML)"} + + external function fx_dec_xmldsig(in bitstring bs, out Signature s) return integer; + /** * @desc Sign message * @param [in] p_encoded_message The raw message to be signed @@ -14,6 +26,7 @@ module LibSecurity_Signature { */ function f_sign( in octetstring p_encoded_message, + in octetstring p_empty_signature, in charstring p_certificate_name, in charstring p_private_key_name, in charstring p_private_key_passwd, @@ -23,10 +36,10 @@ module LibSecurity_Signature { out charstring p_x509_certificate_pem, out charstring p_pull_request_canonicalized ) return integer { - return fx_sign(p_encoded_message, p_certificate_name, p_private_key_name, p_private_key_passwd, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem, p_pull_request_canonicalized); + return fx_sign(p_encoded_message, p_empty_signature, p_certificate_name, p_private_key_name, p_private_key_passwd, p_signature, p_digest, p_x509_certificate_subject, p_x509_certificate_pem, p_pull_request_canonicalized); } - external function fx_sign(in octetstring p_encoded_message, in charstring p_certificate_name, in charstring p_private_key_name, in charstring p_private_key_passwd, out octetstring p_signature, out octetstring p_digest, out charstring p_x509_certificate_subject, out charstring p_x509_certificate_pem, out charstring p_pull_request_canonicalized) return integer; + external function fx_sign(in octetstring p_encoded_message, in octetstring p_empty_signature, in charstring p_certificate_name, in charstring p_private_key_name, in charstring p_private_key_passwd, out octetstring p_signature, out octetstring p_digest, out charstring p_x509_certificate_subject, out charstring p_x509_certificate_pem, out charstring p_pull_request_canonicalized) return integer; /** * @desc Verify signature @@ -35,7 +48,8 @@ module LibSecurity_Signature { * @return true on success, false otherwise */ function f_do_sign_verify( - in charstring p_message, + in charstring p_message, + in octetstring p_empty_signature, in universal charstring p_canonicalization_method, in universal charstring p_signature_method, in universal charstring p_digest_method, @@ -43,11 +57,11 @@ module LibSecurity_Signature { in universal charstring p_signature_value, in universal charstring p_subject_name, in universal charstring p_certificate, - in charstring p_debug_message + out charstring p_debug_message ) return boolean { - return fx_do_sign_verify(p_message, p_canonicalization_method, p_signature_method, p_digest_method, p_digest_value, p_signature_value, p_subject_name, p_certificate, p_debug_message); + return fx_do_sign_verify(p_message, p_empty_signature, p_canonicalization_method, p_signature_method, p_digest_method, p_digest_value, p_signature_value, p_subject_name, p_certificate, p_debug_message); } - external function fx_do_sign_verify(in charstring p_message, in universal charstring p_canonicalization_method, in universal charstring p_signature_method, in universal charstring p_digest_method, in universal charstring p_digest_value, in universal charstring p_signature_value, in universal charstring p_subject_name, in universal charstring p_certificate, in charstring p_debug_message) return boolean; + external function fx_do_sign_verify(in charstring p_message, in octetstring p_empty_signature, in universal charstring p_canonicalization_method, in universal charstring p_signature_method, in universal charstring p_digest_method, in universal charstring p_digest_value, in universal charstring p_signature_value, in universal charstring p_subject_name, in universal charstring p_certificate, out charstring p_debug_message) return boolean; } // End of LibSecurity_Signature \ No newline at end of file diff --git a/ttcn/LibSecurity/ttcn/http_www_w3_org_2000_09_xmldsig.ttcn b/ttcn/LibSecurity/ttcn/http_www_w3_org_2000_09_xmldsig.ttcn new file mode 100644 index 0000000..5bea6b7 --- /dev/null +++ b/ttcn/LibSecurity/ttcn/http_www_w3_org_2000_09_xmldsig.ttcn @@ -0,0 +1,110 @@ +/******************************************************************************* +* Copyright (c) 2000-2022 Ericsson Telecom AB +* +* XSD to TTCN-3 Translator version: CRL 113 200/6 R6B +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v2.0 +* which accompanies this distribution, and is available at +* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html +*******************************************************************************/ +// +// File: http_www_w3_org_2000_09_xmldsig.ttcn +// Description: +// References: +// Rev: +// Prodnr: +// Updated: Thu Jul 7 00:55:24 2022 +// Contact: http://ttcn.ericsson.se +// +//////////////////////////////////////////////////////////////////////////////// +// Generated from file(s): +// - signature.xsd +// /* xml version = "1.0" encoding = "utf-8" */ +// /* targetnamespace = "http://www.w3.org/2000/09/xmldsig#" */ +//////////////////////////////////////////////////////////////////////////////// +// Modification header(s): +//----------------------------------------------------------------------------- +// Modified by: +// Modification date: +// Description: +// Modification contact: +//------------------------------------------------------------------------------ +//////////////////////////////////////////////////////////////////////////////// + + +module http_www_w3_org_2000_09_xmldsig { + + +import from XSD all; + +//import from http_www_cise_eu_sevicemodel_v1_message all; + + +type record Signature +{ + record { + record { + XSD.String algorithm + } canonicalizationMethod, + record { + XSD.String algorithm + } signatureMethod, + record { + XSD.String uRI, + record { + record { + XSD.String algorithm, + XSD.String path + } transform + } transforms, + record { + XSD.String algorithm + } digestMethod, + XSD.String digestValue + } reference + } signedInfo, + XSD.String signatureValue, + record { + record { + XSD.String x509SubjectName, + XSD.String x509Certificate + } x509Data + } keyInfo +} +with { + variant "element"; + variant (signedInfo) "name as capitalized"; + variant (signedInfo.canonicalizationMethod) "name as capitalized"; + variant (signedInfo.canonicalizationMethod.algorithm) "name as capitalized"; + variant (signedInfo.canonicalizationMethod.algorithm) "attribute"; + variant (signedInfo.signatureMethod) "name as capitalized"; + variant (signedInfo.signatureMethod.algorithm) "name as capitalized"; + variant (signedInfo.signatureMethod.algorithm) "attribute"; + variant (signedInfo.reference) "name as capitalized"; + variant (signedInfo.reference.uRI) "name as capitalized"; + variant (signedInfo.reference.uRI) "attribute"; + variant (signedInfo.reference.transforms) "name as capitalized"; + variant (signedInfo.reference.transforms.transform) "name as capitalized"; + variant (signedInfo.reference.transforms.transform.algorithm) "name as capitalized"; + variant (signedInfo.reference.transforms.transform.algorithm) "attribute"; + variant (signedInfo.reference.transforms.transform.path) "untagged"; + variant (signedInfo.reference.digestMethod) "name as capitalized"; + variant (signedInfo.reference.digestMethod.algorithm) "name as capitalized"; + variant (signedInfo.reference.digestMethod.algorithm) "attribute"; + variant (signedInfo.reference.digestValue) "name as capitalized"; + variant (signatureValue) "name as capitalized"; + variant (keyInfo) "name as capitalized"; + variant (keyInfo.x509Data) "name as capitalized"; + variant (keyInfo.x509Data.x509SubjectName) "name as capitalized"; + variant (keyInfo.x509Data.x509Certificate) "name as capitalized"; +}; + + +} +with { + encode "XML"; + variant "namespace as 'http://www.w3.org/2000/09/xmldsig#'"; + variant "controlNamespace 'http://www.w3.org/2001/XMLSchema-instance' prefix 'xsi'"; + variant "elementFormQualified"; +} -- GitLab From c4d93f6e22d71386d5a5949ba1bd447e728ea060 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Fri, 31 Mar 2023 14:55:39 +0200 Subject: [PATCH 18/37] Add UpperTester support --- ccsrc/security/src/security_externals.cc | 10 +++++----- ttcn/LibHttp/ttcn/LibHttp_TestSystem.ttcn | 7 +++---- ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn | 13 ++++++------- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/ccsrc/security/src/security_externals.cc b/ccsrc/security/src/security_externals.cc index e129ea7..5150be2 100644 --- a/ccsrc/security/src/security_externals.cc +++ b/ccsrc/security/src/security_externals.cc @@ -129,7 +129,7 @@ OCTETSTRING LibSecurity__Hash::fx__hash(const OCTETSTRING& p_to_be_hashed, const return hash; } -OCTETSTRING LibSecurity__Signature::fx__enc__xmldsig__signed__info(const http__www__w3__org__2000__09__xmldsig::Signature_signedInfo& s) { // FIXME Use enc/dec TITAN function external function f_enc_value(in Value x) return bitstring with { extension "prototype(convert) encode(abc)" } +BITSTRING LibSecurity__Signature::fx__enc__xmldsig__signed__info(const http__www__w3__org__2000__09__xmldsig::Signature_signedInfo& s) { // FIXME Use enc/dec TITAN function external function f_enc_value(in Value x) return bitstring with { extension "prototype(convert) encode(abc)" } loggers::get_instance().log(">>> fx__enc__xmldsig__signed__info"); TTCN_EncDec::clear_error(); @@ -147,10 +147,10 @@ OCTETSTRING LibSecurity__Signature::fx__enc__xmldsig__signed__info(const http__w OCTETSTRING os = char2oct(CHARSTRING(str.c_str())); loggers::get_instance().log_msg("fx__enc__xmldsig__signed__info: os: ", os); - return os; + return oct2bit(os); } -OCTETSTRING LibSecurity__Signature::fx__enc__xmldsig(const http__www__w3__org__2000__09__xmldsig::Signature& s) { // FIXME Use enc/dec TITAN function external function f_enc_value(in Value x) return bitstring with { extension "prototype(convert) encode(abc)" } +BITSTRING LibSecurity__Signature::fx__enc__xmldsig(const http__www__w3__org__2000__09__xmldsig::Signature& s) { // FIXME Use enc/dec TITAN function external function f_enc_value(in Value x) return bitstring with { extension "prototype(convert) encode(abc)" } loggers::get_instance().log(">>> fx__enc__xmldsig"); TTCN_EncDec::clear_error(); @@ -168,10 +168,10 @@ OCTETSTRING LibSecurity__Signature::fx__enc__xmldsig(const http__www__w3__org__2 OCTETSTRING os = char2oct(CHARSTRING(str.c_str())); loggers::get_instance().log_msg("fx__enc__xmldsig: os: ", os); - return os; + return oct2bit(os); } -INTEGER LibSecurity__Signature::fx__dec__xmldsig(const BITSTRING& bs, http__www__w3__org__2000__09__xmldsig::Signature& s) { // FIXME Use enc/dec TITAN function external function f_enc_value(in Value x) return bitstring with { extension "prototype(convert) encode(abc)" } +INTEGER LibSecurity__Signature::fx__dec__xmldsig(BITSTRING& bs, http__www__w3__org__2000__09__xmldsig::Signature& s) { // FIXME Use enc/dec TITAN function external function f_enc_value(in Value x) return bitstring with { extension "prototype(convert) encode(abc)" } loggers::get_instance().log(">>> fx__dec__xmldsig"); std::string str(static_cast(oct2char(bit2oct(bs)))); diff --git a/ttcn/LibHttp/ttcn/LibHttp_TestSystem.ttcn b/ttcn/LibHttp/ttcn/LibHttp_TestSystem.ttcn index 767bc83..9d0271c 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_TestSystem.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_TestSystem.ttcn @@ -22,19 +22,18 @@ module LibHttp_TestSystem { inout HttpMessage; } - type component HttpComponent extends SelfSyncComp { // FIXME To be rename into HttpTest + type component HttpComponent extends SelfSyncComp { port HttpPort httpPort; port HttpPort httpPort_notif; // timers timer tc_wait := PX_TWAIT; timer tc_ac := PX_TAC; timer tc_noac := PX_TNOAC; - } // End of component HttpComponent - type component HttpTestAdapter { // FIXME To be rename into HttpTestSystem + type component HttpTestAdapter { port HttpPort httpPort; port HttpPort httpPort_notif; - } // End of component TestAdapter + } // End of component HttpTestAdapter } // End of module LibHttp_TestSystem diff --git a/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn b/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn index bf2b5e1..1d0b524 100644 --- a/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn +++ b/ttcn/LibSecurity/ttcn/LibSecurity_Signature.ttcn @@ -2,15 +2,14 @@ module LibSecurity_Signature { import from http_www_w3_org_2000_09_xmldsig all; - external function fx_enc_xmldsig_signed_info(in Signature.signedInfo s) return octetstring; // Use encvalue decoration - //external function fx_enc_PullRequest_1(in PullRequest p_pull_request) return bitstring with {extension "prototype(convert) encode(XML)"} - //external function fx_dec_PullRequest_1(inout bitstring b, out PullRequest p_pull_request)return integer with {extension "prototype(sliding) decode(XML)"} + external function fx_enc_xmldsig_signed_info(in Signature.signedInfo s) return bitstring + with {extension "prototype(convert) encode(XML)"}; - external function fx_enc_xmldsig(in Signature s) return octetstring; // Use encvalue decoration - //external function fx_enc_PullRequest_1(in PullRequest p_pull_request) return bitstring with {extension "prototype(convert) encode(XML)"} - //external function fx_dec_PullRequest_1(inout bitstring b, out PullRequest p_pull_request)return integer with {extension "prototype(sliding) decode(XML)"} + external function fx_enc_xmldsig(in Signature s) return bitstring + with {extension "prototype(convert) encode(XML)"}; - external function fx_dec_xmldsig(in bitstring bs, out Signature s) return integer; + external function fx_dec_xmldsig(inout bitstring bs, out Signature s) return integer + with {extension "prototype(sliding) decode(XML)"}; /** * @desc Sign message -- GitLab From a040768df15ed7029435927562e006baa95c14d1 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Fri, 21 Apr 2023 14:35:54 +0200 Subject: [PATCH 19/37] Add logs to match with cise-simu logs --- ccsrc/security/src/certs_loader.cc | 4 ++-- ccsrc/security/src/securty_services.cc | 14 +++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/ccsrc/security/src/certs_loader.cc b/ccsrc/security/src/certs_loader.cc index ec98eae..91bd87b 100644 --- a/ccsrc/security/src/certs_loader.cc +++ b/ccsrc/security/src/certs_loader.cc @@ -77,7 +77,7 @@ int certs_loader::get_certificate_id(const std::string& p_certificate_name, std: } int certs_loader::load_certificate(const std::string& p_certificate_name, const std::string& p_private_key_name, const std::string& p_private_key_passwd, std::string& p_certificate_id, std::map> & p_certificates) { - loggers::get_instance().log(">>> certs_loader::load_certificate '%s'", p_certificate_name.c_str()); + loggers::get_instance().log(">>> certs_loader::load_certificate: '%s'", p_certificate_name.c_str()); loggers::get_instance().log(">>> certs_loader::load_certificate: '%s'", p_private_key_name.c_str()); // Load certificate file @@ -115,7 +115,7 @@ int certs_loader::load_certificate(const std::string& p_certificate_name, const } std::string pem(mem->data, mem->length); // Remove labels - //loggers::get_instance().log("certs_loader::load_certificate: certificate pem (1): '%s'", pem.c_str()); + loggers::get_instance().log("certs_loader::load_certificate: certificate pem (1): '%s'", pem.c_str()); std::string s("-----BEGIN CERTIFICATE-----\n"); std::string::size_type idx = pem.find_first_of(s); pem = pem.substr(s.length()); diff --git a/ccsrc/security/src/securty_services.cc b/ccsrc/security/src/securty_services.cc index c5fcc95..3c343f9 100644 --- a/ccsrc/security/src/securty_services.cc +++ b/ccsrc/security/src/securty_services.cc @@ -132,6 +132,8 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const OCTET canonicalized = canonicalized.substr(0, i + 13) + std::string(to64.cbegin(), to64.cend()) + canonicalized.substr(i + 13, canonicalized.length() - i - 13); OCTETSTRING to_be_signed(char2oct(CHARSTRING(canonicalized.c_str()))); loggers::get_instance().log_msg("security_services::do_sign: to_be_signed: ", to_be_signed); + to64 = converter::get_instance().buffer_to_base64(std::vector(static_cast(to_be_signed), to_be_signed.lengthof() + static_cast(to_be_signed))); + loggers::get_instance().log("security_services::do_sign: Data to be signed/verified: '%s'", converter::get_instance().bytes_to_string(to64).c_str()); // Retrive the private key const EVP_PKEY* private_key; @@ -237,16 +239,16 @@ bool security_services::do_sign_verify(const CHARSTRING& p_message, const OCTETS // Transform: Remove all CR, LS, TAB and SPACE outside of the tags transformed.clear(); xml_converters::get_instance().xml_transform(std::string((const char*)(static_cast(p_empty_signature)), p_empty_signature.lengthof()), transformed); - loggers::get_instance().log("security_services::do_sign: p_empty_signature transormed: '%s'", transformed.c_str()); + loggers::get_instance().log("security_services::do_sign_verify: p_empty_signature transormed: '%s'", transformed.c_str()); // Canonicalization canonicalized.clear(); xml_converters::get_instance().xml_canonicalization(transformed, canonicalized); - loggers::get_instance().log("security_services::do_sign: p_empty_signature canonicalized: '%s'", canonicalized.c_str()); + loggers::get_instance().log("security_services::do_sign_verify: p_empty_signature canonicalized: '%s'", canonicalized.c_str()); // Compute the digest of the transformed/canonicalized message - loggers::get_instance().log_msg("security_services::do_sign: compute digest for ", v_pull_request_canonicalized); + loggers::get_instance().log_msg("security_services::do_sign_verify: compute digest for ", v_pull_request_canonicalized); int first = canonicalized.find("xmldsig#sha1"); - loggers::get_instance().log("security_services::do_sign: p_empty_signature first: '%d'", first); + loggers::get_instance().log("security_services::do_sign_verify: p_empty_signature first: '%d'", first); OCTETSTRING dg; const EVP_MD* sign_digest; if (first != -1) { @@ -322,7 +324,9 @@ bool security_services::do_sign_verify(const CHARSTRING& p_message, const OCTETS int i = canonicalized.find(""); canonicalized = canonicalized.substr(0, i + 13) + std::string(to64.cbegin(), to64.cend()) + canonicalized.substr(i + 13, canonicalized.length() - i - 13); OCTETSTRING to_be_signed(char2oct(CHARSTRING(canonicalized.c_str()))); - loggers::get_instance().log_msg("security_services::do_sign: to_be_signed: ", to_be_signed); + loggers::get_instance().log_msg("security_services::do_sign_verify: to_be_signed: ", to_be_signed); + to64 = converter::get_instance().buffer_to_base64(std::vector(static_cast(to_be_signed), to_be_signed.lengthof() + static_cast(to_be_signed))); + loggers::get_instance().log("security_services::do_sign_verify: Data to be signed/verified: '%s'", converter::get_instance().bytes_to_string(to64).c_str()); // Convert signature std::string signature_value(static_cast(unichar2char(p_signature_value))); -- GitLab From 19de911db44446712fba89bce73c3517cfc5d7ed Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Tue, 2 May 2023 14:26:30 +0200 Subject: [PATCH 20/37] Support of implicit certificates step1: Public key reconstruction --- ccsrc/security/include/sha1.hh | 132 +++++++++++++++---------------- ccsrc/security/include/sha256.hh | 132 +++++++++++++++---------------- ccsrc/security/include/sha384.hh | 120 ++++++++++++++-------------- ccsrc/security/module.mk | 1 + ccsrc/security/src/sha1.cc | 78 +++++++++--------- ccsrc/security/src/sha256.cc | 78 +++++++++--------- ccsrc/security/src/sha384.cc | 94 +++++++++++----------- 7 files changed, 318 insertions(+), 317 deletions(-) diff --git a/ccsrc/security/include/sha1.hh b/ccsrc/security/include/sha1.hh index 69f35da..e053544 100644 --- a/ccsrc/security/include/sha1.hh +++ b/ccsrc/security/include/sha1.hh @@ -1,66 +1,66 @@ -/*! - * \file sha1.hh - * \brief Header file for SHA-1 helper methods. - * \author ETSI STF637 - * \copyright ETSI Copyright Notification - * No part may be reproduced except as authorized by written permission. - * The copyright and the foregoing restriction extend to reproduction in all media. - * All rights reserved. - * \version 0.1 - */ -#pragma once - -#include -#include - -class OCTETSTRING; //! TITAN forward declaration - -/*! - * \class sha1 - * \brief This class provides description of SHA-1 helper methods - */ -class sha1 { - SHA_CTX _ctx; //! SHA context -public: - /*! - * \brief Default constructor - * Create a new instance of the sha1 class - */ - explicit sha1() : _ctx{} {}; - /*! - * \brief Default destructor - */ - virtual ~sha1(){}; - - /*! - * \fn int generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash); - * \brief Receive bytes formated data from the lower layers - * \param[in] p_buffer The data used to generate the SHA-1 hash - * \param[out] p_hash The SHA-1 hash value based of the provided data - * \return 0 on success, -1 otherwise - */ - int generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash); - - /*! - * \fn int generate(const unsigned char* p_buffer, OCTETSTRING& p_hash); - * \brief Receive bytes formated data from the lower layers - * \param[in] p_buffer The data used to generate the SHA-1 hash - * \param[in] The length of the data buffer - * \param[out] p_hash The SHA-1 hash value based of the provided data - * \return 0 on success, -1 otherwise - */ - int generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash); - - /*! - * \fn const OCTETSTRING get_sha1_empty_string() const; - * \brief Return the SHA-1 of an empty string - * \return The SHA-1 of an empty string - */ - inline const OCTETSTRING get_sha1_empty_string() const { - static unsigned char sha1_empty_string[] = { - 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, - 0xaf, 0xd8, 0x07, 0x09}; //! SHA-1 of an empty string - return OCTETSTRING(20, sha1_empty_string); - }; - -}; // End of class sha1 +/*! + * \file sha1.hh + * \brief Header file for SHA-1 helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include +#include + +class OCTETSTRING; //! TITAN forward declaration + +/*! + * \class sha1 + * \brief This class provides description of SHA-1 helper methods + */ +class sha1 { + SHA_CTX _ctx; //! SHA context +public: + /*! + * \brief Default constructor + * Create a new instance of the sha1 class + */ + explicit sha1() : _ctx{} {}; + /*! + * \brief Default destructor + */ + virtual ~sha1(){}; + + /*! + * \fn int generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The data used to generate the SHA-1 hash + * \param[out] p_hash The SHA-1 hash value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash); + + /*! + * \fn int generate(const unsigned char* p_buffer, OCTETSTRING& p_hash); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The data used to generate the SHA-1 hash + * \param[in] The length of the data buffer + * \param[out] p_hash The SHA-1 hash value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash); + + /*! + * \fn const OCTETSTRING get_sha1_empty_string() const; + * \brief Return the SHA-1 of an empty string + * \return The SHA-1 of an empty string + */ + inline const OCTETSTRING get_sha1_empty_string() const { + static unsigned char sha1_empty_string[] = { + 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, + 0xaf, 0xd8, 0x07, 0x09}; //! SHA-1 of an empty string + return OCTETSTRING(20, sha1_empty_string); + }; + +}; // End of class sha1 diff --git a/ccsrc/security/include/sha256.hh b/ccsrc/security/include/sha256.hh index fbb972d..4973a2e 100644 --- a/ccsrc/security/include/sha256.hh +++ b/ccsrc/security/include/sha256.hh @@ -1,66 +1,66 @@ -/*! - * \file sha256.hh - * \brief Header file for SHA-256 helper methods. - * \author ETSI STF637 - * \copyright ETSI Copyright Notification - * No part may be reproduced except as authorized by written permission. - * The copyright and the foregoing restriction extend to reproduction in all media. - * All rights reserved. - * \version 0.1 - */ -#pragma once - -#include -#include - -class OCTETSTRING; //! TITAN forward declaration - -/*! - * \class sha256 - * \brief This class provides description of SHA-256 helper methods - */ -class sha256 { - SHA256_CTX _ctx; //! SHA context -public: - /*! - * \brief Default constructor - * Create a new instance of the sha256 class - */ - explicit sha256() : _ctx{} {}; - /*! - * \brief Default destructor - */ - virtual ~sha256(){}; - - /*! - * \fn int generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash); - * \brief Receive bytes formated data from the lower layers - * \param[in] p_buffer The data used to generate the SHA-256 hash - * \param[out] p_hash The SHA-256 hash value based of the provided data - * \return 0 on success, -1 otherwise - */ - int generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash); - - /*! - * \fn int generate(const unsigned char* p_buffer, OCTETSTRING& p_hash); - * \brief Receive bytes formated data from the lower layers - * \param[in] p_buffer The data used to generate the SHA-256 hash - * \param[in] The length of the data buffer - * \param[out] p_hash The SHA-256 hash value based of the provided data - * \return 0 on success, -1 otherwise - */ - int generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash); - - /*! - * \fn const OCTETSTRING get_sha256_empty_string() const; - * \brief Return the SHA-256 of an empty string - * \return The SHA-256 of an empty string - */ - inline const OCTETSTRING get_sha256_empty_string() const { - static unsigned char sha256_empty_string[] = { - 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, - 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; //! SHA-256 of an empty string - return OCTETSTRING(32, sha256_empty_string); - }; - -}; // End of class sha256 +/*! + * \file sha256.hh + * \brief Header file for SHA-256 helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include +#include + +class OCTETSTRING; //! TITAN forward declaration + +/*! + * \class sha256 + * \brief This class provides description of SHA-256 helper methods + */ +class sha256 { + SHA256_CTX _ctx; //! SHA context +public: + /*! + * \brief Default constructor + * Create a new instance of the sha256 class + */ + explicit sha256() : _ctx{} {}; + /*! + * \brief Default destructor + */ + virtual ~sha256(){}; + + /*! + * \fn int generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The data used to generate the SHA-256 hash + * \param[out] p_hash The SHA-256 hash value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash); + + /*! + * \fn int generate(const unsigned char* p_buffer, OCTETSTRING& p_hash); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The data used to generate the SHA-256 hash + * \param[in] The length of the data buffer + * \param[out] p_hash The SHA-256 hash value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash); + + /*! + * \fn const OCTETSTRING get_sha256_empty_string() const; + * \brief Return the SHA-256 of an empty string + * \return The SHA-256 of an empty string + */ + inline const OCTETSTRING get_sha256_empty_string() const { + static unsigned char sha256_empty_string[] = { + 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; //! SHA-256 of an empty string + return OCTETSTRING(32, sha256_empty_string); + }; + +}; // End of class sha256 diff --git a/ccsrc/security/include/sha384.hh b/ccsrc/security/include/sha384.hh index 016c54f..67f2d19 100644 --- a/ccsrc/security/include/sha384.hh +++ b/ccsrc/security/include/sha384.hh @@ -1,60 +1,60 @@ -/*! - * \file sha384.hh - * \brief Header file for SHA-384 helper methods. - * \author ETSI STF637 - * \copyright ETSI Copyright Notification - * No part may be reproduced except as authorized by written permission. - * The copyright and the foregoing restriction extend to reproduction in all media. - * All rights reserved. - * \version 0.1 - */ -#pragma once - -#include -#include - -class OCTETSTRING; //! TITAN forward declaration - -/*! - * \class sha384 - * \brief This class provides description of SHA-384 helper methods - */ -class sha384 { - SHA512_CTX _ctx; //! SHA context -public: //! \publicsection - /*! - * \brief Default constructor - * Create a new instance of the sha384 class - */ - explicit sha384() : _ctx{} {}; - /*! - * \brief Default destructor - */ - virtual ~sha384(){}; - - /*! - * \fn int generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash); - * \brief Receive bytes formated data from the lower layers - * \param[in] p_buffer The data used to generate the SHA-384 hash - * \param[out] p_hash The SHA-384 hash value based of the provided data - * \return 0 on success, -1 otherwise - */ - int generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash); - - /*! - * \fn int generate(const OCTETSTRING p_buffer, OCTETSTRING& p_hash); - * \brief Receive bytes formated data from the lower layers - * \param[in] p_buffer The data used to generate the SHA-384 hash - * \param[in] The length of the data buffer - * \param[out] p_hash The SHA-384 hash value based of the provided data - * \return 0 on success, -1 otherwise - */ - int generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash); - - /*! - * \fn const OCTETSTRING get_sha384_empty_string() const; - * \brief Return the SHA-384 of an empty string - * \return The SHA-384 of an empty string - */ - const OCTETSTRING get_sha384_empty_string() const; -}; // End of class sha384 +/*! + * \file sha384.hh + * \brief Header file for SHA-384 helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#pragma once + +#include +#include + +class OCTETSTRING; //! TITAN forward declaration + +/*! + * \class sha384 + * \brief This class provides description of SHA-384 helper methods + */ +class sha384 { + SHA512_CTX _ctx; //! SHA context +public: //! \publicsection + /*! + * \brief Default constructor + * Create a new instance of the sha384 class + */ + explicit sha384() : _ctx{} {}; + /*! + * \brief Default destructor + */ + virtual ~sha384(){}; + + /*! + * \fn int generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The data used to generate the SHA-384 hash + * \param[out] p_hash The SHA-384 hash value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash); + + /*! + * \fn int generate(const OCTETSTRING p_buffer, OCTETSTRING& p_hash); + * \brief Receive bytes formated data from the lower layers + * \param[in] p_buffer The data used to generate the SHA-384 hash + * \param[in] The length of the data buffer + * \param[out] p_hash The SHA-384 hash value based of the provided data + * \return 0 on success, -1 otherwise + */ + int generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash); + + /*! + * \fn const OCTETSTRING get_sha384_empty_string() const; + * \brief Return the SHA-384 of an empty string + * \return The SHA-384 of an empty string + */ + const OCTETSTRING get_sha384_empty_string() const; +}; // End of class sha384 diff --git a/ccsrc/security/module.mk b/ccsrc/security/module.mk index e05c42d..114a8ab 100644 --- a/ccsrc/security/module.mk +++ b/ccsrc/security/module.mk @@ -9,5 +9,6 @@ sources := \ src/sha256.cc \ src/sha384.cc \ src/hmac.cc \ + # src/sm3.cc \ includes := ./include diff --git a/ccsrc/security/src/sha1.cc b/ccsrc/security/src/sha1.cc index bd9386d..21b0514 100644 --- a/ccsrc/security/src/sha1.cc +++ b/ccsrc/security/src/sha1.cc @@ -1,39 +1,39 @@ -/*! - * \file sha1.cc - * \brief Source file for SHA-1 helper methods. - * \author ETSI STF637 - * \copyright ETSI Copyright Notification - * No part may be reproduced except as authorized by written permission. - * The copyright and the foregoing restriction extend to reproduction in all media. - * All rights reserved. - * \version 0.1 - */ -#include - -#include "sha1.hh" - -int sha1::generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash) { - // Sanity check - if (p_buffer.lengthof() == 0) { - p_hash = get_sha1_empty_string(); - return 0; - } - - return generate(static_cast(p_buffer), p_buffer.lengthof(), p_hash); -} - -int sha1::generate(const unsigned char* p_buffer, const size_t p_length, OCTETSTRING& p_hash) { - // Sanity check - if ((p_buffer == nullptr) || (p_length == 0)) { - p_hash = get_sha1_empty_string(); - return 0; - } - - // Resize data buffer - p_hash = int2oct(0, SHA_DIGEST_LENGTH); - // Compute the hash value - ::SHA1_Init(&_ctx); - ::SHA1_Update(&_ctx, p_buffer, p_length); - ::SHA1_Final((unsigned char*)static_cast(p_hash), &_ctx); - return 0; -}; +/*! + * \file sha1.cc + * \brief Source file for SHA-1 helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#include + +#include "sha1.hh" + +int sha1::generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash) { + // Sanity check + if (p_buffer.lengthof() == 0) { + p_hash = get_sha1_empty_string(); + return 0; + } + + return generate(static_cast(p_buffer), p_buffer.lengthof(), p_hash); +} + +int sha1::generate(const unsigned char* p_buffer, const size_t p_length, OCTETSTRING& p_hash) { + // Sanity check + if ((p_buffer == nullptr) || (p_length == 0)) { + p_hash = get_sha1_empty_string(); + return 0; + } + + // Resize data buffer + p_hash = int2oct(0, SHA_DIGEST_LENGTH); + // Compute the hash value + ::SHA1_Init(&_ctx); + ::SHA1_Update(&_ctx, p_buffer, p_length); + ::SHA1_Final((unsigned char*)static_cast(p_hash), &_ctx); + return 0; +}; diff --git a/ccsrc/security/src/sha256.cc b/ccsrc/security/src/sha256.cc index e1fdf07..2238f09 100644 --- a/ccsrc/security/src/sha256.cc +++ b/ccsrc/security/src/sha256.cc @@ -1,39 +1,39 @@ -/*! - * \file sha256.cc - * \brief Source file for SHA-256 helper methods. - * \author ETSI STF637 - * \copyright ETSI Copyright Notification - * No part may be reproduced except as authorized by written permission. - * The copyright and the foregoing restriction extend to reproduction in all media. - * All rights reserved. - * \version 0.1 - */ -#include - -#include "sha256.hh" - -int sha256::generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash) { - // Sanity check - if (p_buffer.lengthof() == 0) { - p_hash = get_sha256_empty_string(); - return 0; - } - - return generate(static_cast(p_buffer), p_buffer.lengthof(), p_hash); -} - -int sha256::generate(const unsigned char* p_buffer, const size_t p_length, OCTETSTRING& p_hash) { - // Sanity check - if ((p_buffer == nullptr) || (p_length == 0)) { - p_hash = get_sha256_empty_string(); - return 0; - } - - // Resize data buffer - p_hash = int2oct(0, SHA256_DIGEST_LENGTH); - // Compute the hash value - ::SHA256_Init(&_ctx); - ::SHA256_Update(&_ctx, p_buffer, p_length); - ::SHA256_Final((unsigned char*)static_cast(p_hash), &_ctx); - return 0; -}; +/*! + * \file sha256.cc + * \brief Source file for SHA-256 helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#include + +#include "sha256.hh" + +int sha256::generate(const OCTETSTRING& p_buffer, OCTETSTRING& p_hash) { + // Sanity check + if (p_buffer.lengthof() == 0) { + p_hash = get_sha256_empty_string(); + return 0; + } + + return generate(static_cast(p_buffer), p_buffer.lengthof(), p_hash); +} + +int sha256::generate(const unsigned char* p_buffer, const size_t p_length, OCTETSTRING& p_hash) { + // Sanity check + if ((p_buffer == nullptr) || (p_length == 0)) { + p_hash = get_sha256_empty_string(); + return 0; + } + + // Resize data buffer + p_hash = int2oct(0, SHA256_DIGEST_LENGTH); + // Compute the hash value + ::SHA256_Init(&_ctx); + ::SHA256_Update(&_ctx, p_buffer, p_length); + ::SHA256_Final((unsigned char*)static_cast(p_hash), &_ctx); + return 0; +}; diff --git a/ccsrc/security/src/sha384.cc b/ccsrc/security/src/sha384.cc index 9ad92fb..b32e4c2 100644 --- a/ccsrc/security/src/sha384.cc +++ b/ccsrc/security/src/sha384.cc @@ -1,47 +1,47 @@ -/*! - * \file sha384.cc - * \brief Sorce file for SHA-384 helper methods. - * \author ETSI STF637 - * \copyright ETSI Copyright Notification - * No part may be reproduced except as authorized by written permission. - * The copyright and the foregoing restriction extend to reproduction in all media. - * All rights reserved. - * \version 0.1 - */ -#include - -#include "sha384.hh" - -int sha384::generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash) { - // Sanity check - if (p_buffer.lengthof() == 0) { - p_hash = get_sha384_empty_string(); - return 0; - } - - return generate(static_cast(p_buffer), p_buffer.lengthof(), p_hash); -} - -int sha384::generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash) { - // Sanity check - if ((p_buffer == nullptr) || (p_length == 0)) { - p_hash = get_sha384_empty_string(); - return 0; - } - - // Resize data buffer - p_hash = int2oct(0, SHA384_DIGEST_LENGTH); - // Compute the hash value - ::SHA384_Init(&_ctx); - ::SHA384_Update(&_ctx, p_buffer, p_length); - ::SHA384_Final((unsigned char *)static_cast(p_hash), &_ctx); - return 0; -} - -const OCTETSTRING sha384::get_sha384_empty_string() const { - static unsigned char - sha384_empty_string[] = {0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, - 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, - 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b}; //! SHA-384 of an empty string - return OCTETSTRING(48, sha384_empty_string); -} +/*! + * \file sha384.cc + * \brief Sorce file for SHA-384 helper methods. + * \author ETSI STF637 + * \copyright ETSI Copyright Notification + * No part may be reproduced except as authorized by written permission. + * The copyright and the foregoing restriction extend to reproduction in all media. + * All rights reserved. + * \version 0.1 + */ +#include + +#include "sha384.hh" + +int sha384::generate(const OCTETSTRING &p_buffer, OCTETSTRING &p_hash) { + // Sanity check + if (p_buffer.lengthof() == 0) { + p_hash = get_sha384_empty_string(); + return 0; + } + + return generate(static_cast(p_buffer), p_buffer.lengthof(), p_hash); +} + +int sha384::generate(const unsigned char *p_buffer, const size_t p_length, OCTETSTRING &p_hash) { + // Sanity check + if ((p_buffer == nullptr) || (p_length == 0)) { + p_hash = get_sha384_empty_string(); + return 0; + } + + // Resize data buffer + p_hash = int2oct(0, SHA384_DIGEST_LENGTH); + // Compute the hash value + ::SHA384_Init(&_ctx); + ::SHA384_Update(&_ctx, p_buffer, p_length); + ::SHA384_Final((unsigned char *)static_cast(p_hash), &_ctx); + return 0; +} + +const OCTETSTRING sha384::get_sha384_empty_string() const { + static unsigned char + sha384_empty_string[] = {0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, + 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, + 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b}; //! SHA-384 of an empty string + return OCTETSTRING(48, sha384_empty_string); +} -- GitLab From 163d1cfca22b18ceb1d7e24380f46f7fbaa53a97 Mon Sep 17 00:00:00 2001 From: garciay Date: Tue, 9 May 2023 14:22:07 +0200 Subject: [PATCH 21/37] Prepare CDM#44 demo --- ccsrc/Helpers/helpers_externals.cc | 2 +- ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ccsrc/Helpers/helpers_externals.cc b/ccsrc/Helpers/helpers_externals.cc index d4dfde6..c9f2ec7 100644 --- a/ccsrc/Helpers/helpers_externals.cc +++ b/ccsrc/Helpers/helpers_externals.cc @@ -127,7 +127,7 @@ namespace LibHelpers__Functions { time_t t = std::time(nullptr); auto tm = *std::localtime(&t); std::ostringstream oss; - oss << std::put_time(&tm, "%FT%T");//%FT%T%Z + oss << std::put_time(&tm, "%FT%TZ");//%FT%T%Z CHARSTRING dt(oss.str().c_str()); loggers::get_instance().log_msg("fx__get__current__date__time: ", dt); diff --git a/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn b/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn index b5eb352..fc641a2 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn @@ -223,6 +223,14 @@ module LibHttp_Templates { statustext := "Created" } // End of template mw_http_response_201_created + template (present) Response mw_http_response_201_created_no_status_text( + template (present) HttpMessageBody p_body := ?, + template (present) Headers p_header := ? + ) modifies mw_http_response_ok := { + statuscode := 201, + statustext := ? + } // End of template mw_http_response_201_created_no_status_text + template (present) Response mw_http_response_202_accepted( template (present) HttpMessageBody p_body := ?, template (present) Headers p_header := ? -- GitLab From 2645a5245082506a64acc58e7c2c7ac5c5bc4c3a Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Fri, 12 May 2023 08:45:53 +0200 Subject: [PATCH 22/37] Add encode XML variant --- ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn b/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn index dbc3401..343caf1 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn @@ -19,6 +19,11 @@ module LibHttp_XmlMessageBodyTypes { } } with { +<<<<<<< Updated upstream variant ""; encode "XML" +======= + encode "XML"; + variant "" +>>>>>>> Stashed changes } // End of LibHttp_XmlMessageBodyTypes -- GitLab From 5194450f739680aa9a5d516f8c3c3f3b7a782773 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Mon, 15 May 2023 07:32:25 +0200 Subject: [PATCH 23/37] Remove useless include --- ccsrc/Protocols/Xml/src/xml_converters.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ccsrc/Protocols/Xml/src/xml_converters.cc b/ccsrc/Protocols/Xml/src/xml_converters.cc index 989e62e..4f47eea 100644 --- a/ccsrc/Protocols/Xml/src/xml_converters.cc +++ b/ccsrc/Protocols/Xml/src/xml_converters.cc @@ -16,8 +16,8 @@ #include #include #include -#include -#include +//#include +//#include xml_converters* xml_converters::_instance = nullptr; -- GitLab From 767c0887c2eb6c43a144f02613ae8eb25c4a7516 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Mon, 15 May 2023 14:57:39 +0200 Subject: [PATCH 24/37] Add encode XML variant --- ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn b/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn index 343caf1..96cfb2f 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn @@ -19,11 +19,6 @@ module LibHttp_XmlMessageBodyTypes { } } with { -<<<<<<< Updated upstream - variant ""; - encode "XML" -======= encode "XML"; variant "" ->>>>>>> Stashed changes } // End of LibHttp_XmlMessageBodyTypes -- GitLab From 59e6bf48d2e7960aee7bd8a1b70b208a954cedf5 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Wed, 17 May 2023 10:19:47 +0200 Subject: [PATCH 25/37] Review typing for MEC 012 --- ttcn/LibJson/ttcn/Json.ttcn | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/ttcn/LibJson/ttcn/Json.ttcn b/ttcn/LibJson/ttcn/Json.ttcn index 7fb36ef..ff45ceb 100644 --- a/ttcn/LibJson/ttcn/Json.ttcn +++ b/ttcn/LibJson/ttcn/Json.ttcn @@ -51,6 +51,17 @@ module Json { type integer Integer (-infinity .. infinity) /*with { variant "Json:integer" }*/; + // Unsigned Integer type + type integer UInteger (0 .. infinity) /*with { + variant "Json:integer" + }*/; + // Unsigned char type + type integer UInt8 (0 .. 255) /*with { + variant "Json:integer" + }*/; + type integer UInt16 (0 .. 65535) /*with { + variant "Json:integer" + }*/; // String type type utf8string String /*with { variant "Json:string" @@ -103,11 +114,17 @@ module Json { }*/ type record of Json.Integer IntArray; /*with { variant "Json:array" - } - type record of Json.Bool BoolArray with { + }*/ + type record of Json.UInteger UIntArray; /*with { variant "Json:array" - } - type record of Json.Object ObjArray with { + }*/ + type record of Json.Bool BoolArray; /*with { + variant "Json:array" + }*/ + type record of Json.AnyURI AnyURIArray; /*with { + variant "Json:array" + }*/ + /*type record of Json.Object ObjArray; with { variant "Json:array" }*/ // Object member -- GitLab From 25b94cec2e9370310eabe936d429f54eae02ffd1 Mon Sep 17 00:00:00 2001 From: garciay Date: Tue, 13 Jun 2023 09:23:26 +0200 Subject: [PATCH 26/37] Enhance LibXsd --- ttcn/LibXsd/module.mk | 5 +- ttcn/LibXsd/ttcn/NoTargetNamespace.ttcn | 183 ++++++++++++++++ .../http_www_w3_org_XML_1998_namespace.ttcn | 204 ++++++++++++++++++ 3 files changed, 391 insertions(+), 1 deletion(-) create mode 100644 ttcn/LibXsd/ttcn/NoTargetNamespace.ttcn create mode 100644 ttcn/LibXsd/ttcn/http_www_w3_org_XML_1998_namespace.ttcn diff --git a/ttcn/LibXsd/module.mk b/ttcn/LibXsd/module.mk index edc3ade..d352951 100644 --- a/ttcn/LibXsd/module.mk +++ b/ttcn/LibXsd/module.mk @@ -1,3 +1,6 @@ sources := \ ttcn/UsefulTtcn3Types.ttcn \ - ttcn/XSD.ttcn + ttcn/XSD.ttcn \ + ttcn/NoTargetNamespace.ttcn \ + ttcn/http_www_w3_org_XML_1998_namespace.ttcn \ + diff --git a/ttcn/LibXsd/ttcn/NoTargetNamespace.ttcn b/ttcn/LibXsd/ttcn/NoTargetNamespace.ttcn new file mode 100644 index 0000000..9bf9d29 --- /dev/null +++ b/ttcn/LibXsd/ttcn/NoTargetNamespace.ttcn @@ -0,0 +1,183 @@ +/******************************************************************************* +* Copyright (c) 2000-2016 Ericsson Telecom AB +* +* XSD to TTCN-3 Translator version: CRL 113 200/5 R4D +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* which accompanies this distribution, and is available at +* http://www.eclipse.org/legal/epl-v10.html +*******************************************************************************/ +// +// File: NoTargetNamespace.ttcn +// Description: +// References: +// Rev: +// Prodnr: +// Updated: Fri Mar 4 09:23:30 2016 +// Contact: http://ttcn.ericsson.se +// +//////////////////////////////////////////////////////////////////////////////// +// Generated from file(s): +// - Ims3gpp.xsd +// /* xml version = "1.0" encoding = "UTF-8" */ +// /* targetnamespace = "NoTargetNamespace" */ +//////////////////////////////////////////////////////////////////////////////// +// Modification header(s): +//----------------------------------------------------------------------------- +// Modified by: +// Modification date: +// Description: +// Modification contact: +//------------------------------------------------------------------------------ +//////////////////////////////////////////////////////////////////////////////// + + +module NoTargetNamespace { + + +import from XSD all; + + +type record TIMS3GPP +{ + XSD.Decimal version, + record of XSD.String attr optional, + union { + TAlternativeService alternative_service, + XSD.String service_info + } choice, + record of XSD.String elem_list +} +with { + variant "name as uncapitalized"; + variant (version) "attribute"; + variant (attr) "anyAttributes"; + variant (choice) "untagged"; + variant (choice.alternative_service) "name as 'alternative-service'"; + variant (choice.service_info) "name as 'service-info'"; + variant (elem_list) "untagged"; + variant (elem_list[-]) "anyElement"; +}; + + +type record TAlternativeService +{ + record of XSD.String attr optional, + TType type_, + XSD.String reason, + record of XSD.String elem_list +} +with { + variant "name as uncapitalized"; + variant (attr) "anyAttributes"; + variant (type_) "name as 'type'"; + variant (elem_list) "untagged"; + variant (elem_list[-]) "anyElement"; +}; + + +type record TType +{ + record of XSD.String attr optional, + record of XSD.String elem_list +} +with { + variant "name as uncapitalized"; + variant (attr) "anyAttributes"; + variant (elem_list) "untagged"; + variant (elem_list[-]) "anyElement"; +}; + + +type record TAction +{ + record of XSD.String attr optional, + record of XSD.String elem_list +} +with { + variant "name as uncapitalized"; + variant (attr) "anyAttributes"; + variant (elem_list) "untagged"; + variant (elem_list[-]) "anyElement"; +}; + + +/* root element */ + + +type TIMS3GPP Ims_3gpp +with { + variant "name as 'ims-3gpp'"; + variant "element"; +}; + + +/* emergency element for //ims-3gpp//alternative-service//type */ + + +type record Emergency +{ + +} +with { + variant "name as uncapitalized"; + variant "element"; +}; + + +/* restoration element for //ims-3gpp//alternative-service//type */ + + +type record Restoration +{ + +} +with { + variant "name as uncapitalized"; + variant "element"; +}; + + +/* action element for //ims-3gpp//alternative-service */ + + +type TAction Action +with { + variant "name as uncapitalized"; + variant "element"; +}; + + +/* emergency-registration element for //ims-3gpp//alternative-service//action */ + + +type record Emergency_registration +{ + +} +with { + variant "name as 'emergency-registration'"; + variant "element"; +}; + + +/* initial-registration element for //ims-3gpp//alternative-service//action */ + + +type record Initial_registration +{ + +} +with { + variant "name as 'initial-registration'"; + variant "element"; +}; + + +} +with { + encode "XML"; + variant "controlNamespace 'http://www.w3.org/2001/XMLSchema-instance' prefix 'xsi'"; + variant "elementFormQualified"; +} diff --git a/ttcn/LibXsd/ttcn/http_www_w3_org_XML_1998_namespace.ttcn b/ttcn/LibXsd/ttcn/http_www_w3_org_XML_1998_namespace.ttcn new file mode 100644 index 0000000..dd35e71 --- /dev/null +++ b/ttcn/LibXsd/ttcn/http_www_w3_org_XML_1998_namespace.ttcn @@ -0,0 +1,204 @@ +/******************************************************************************* +* Copyright (c) 2000-2018 Ericsson Telecom AB +* +* XSD to TTCN-3 Translator version: CRL 113 200/6 R4B +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v2.0 +* which accompanies this distribution, and is available at +* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html +*******************************************************************************/ +// +// File: http_www_w3_org_XML_1998_namespace.ttcn +// Description: +// References: +// Rev: +// Prodnr: +// Updated: Tue Aug 7 08:36:53 2018 +// Contact: http://ttcn.ericsson.se +// +//////////////////////////////////////////////////////////////////////////////// +// Generated from file(s): +// - xml_2001.xsd +// /* xml version = "1.0" */ +// /* targetnamespace = "http://www.w3.org/XML/1998/namespace" */ +// - xml.xsd +// /* xml version = "1.0" */ +// /* targetnamespace = "http://www.w3.org/XML/1998/namespace" */ +//////////////////////////////////////////////////////////////////////////////// +// Modification header(s): +//----------------------------------------------------------------------------- +// Modified by: +// Modification date: +// Description: +// Modification contact: +//------------------------------------------------------------------------------ +//////////////////////////////////////////////////////////////////////////////// + + +module http_www_w3_org_XML_1998_namespace { + + +import from XSD all; + + +/* See http://www.w3.org/XML/1998/namespace.html and + http://www.w3.org/TR/REC-xml for information about this namespace. + + This schema document describes the XML namespace, in a form + suitable for import by other schema documents. + + Note that local names in this namespace are intended to be defined + only by the World Wide Web Consortium or its subgroups. The + following names are currently defined in this namespace and should + not be used with conflicting semantics by any Working Group, + specification, or document instance: + + base (as an attribute name): denotes an attribute whose value + provides a URI to be used as the base for interpreting any + relative URIs in the scope of the element on which it + appears; its value is inherited. This name is reserved + by virtue of its definition in the XML Base specification. + + lang (as an attribute name): denotes an attribute whose value + is a language code for the natural language of the content of + any element; its value is inherited. This name is reserved + by virtue of its definition in the XML specification. + + space (as an attribute name): denotes an attribute whose + value is a keyword indicating what whitespace processing + discipline is intended for the content of the element; its + value is inherited. This name is reserved by virtue of its + definition in the XML specification. + + Father (in any context at all): denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and + XML Coordination groups: + + In appreciation for his vision, leadership and dedication + the W3C XML Plenary on this 10th day of February, 2000 + reserves for Jon Bosak in perpetuity the XML name + xml:Father */ + + +/* This schema defines attributes and an attribute group + suitable for use by + schemas wishing to allow xml:base, xml:lang or xml:space attributes + on elements they define. + + To enable this, such a schema must import this schema + for the XML namespace, e.g. as follows: + + . . . + + + Subsequently, qualified reference to any of the attributes + or the group defined below will have the desired effect, e.g. + + + . . . + + + will define a type which will schema-validate an instance + element with any of those attributes */ + + +/* In keeping with the XML Schema WG's standard versioning + policy, this schema document will persist at + http://www.w3.org/2001/03/xml.xsd. + At the date of issue it can also be found at + http://www.w3.org/2001/xml.xsd. + The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XML Schema + itself. In other words, if the XML Schema namespace changes, the version + of this document at + http://www.w3.org/2001/xml.xsd will change + accordingly; the version at + http://www.w3.org/2001/03/xml.xsd will not change. */ + + +/* In due course, we should install the relevant ISO 2- and 3-letter + codes as the enumerated possible values . . . */ +type XSD.Language Lang +with { + variant "name as uncapitalized"; + variant "attribute"; +}; + + +type enumerated Space +{ + default_, + preserve +} +with { + variant "text 'default_' as 'default'"; + variant "defaultForEmpty as c_defaultForEmpty_1"; + variant "name as uncapitalized"; + variant "attribute"; +}; + + +/* See http://www.w3.org/TR/xmlbase/ for + information about this attribute. */ +type XSD.AnyURI Base +with { + variant "name as uncapitalized"; + variant "attribute"; +}; + + +const Space c_defaultForEmpty_1 := preserve; + + +type union Lang_1 +{ + XSD.Language language_, + enumerated { + x + } alt_ +} +with { + variant "name as 'lang'"; + variant "useUnion"; + variant "attribute"; + variant (language_) "name as 'language'"; + variant (alt_) "name as ''"; + variant (alt_) "text 'x' as ''"; +}; + + +type enumerated Space_1 +{ + default_, + preserve +} +with { + variant "text 'default_' as 'default'"; + variant "name as 'space'"; + variant "attribute"; +}; + + +type XSD.AnyURI Base_1 +with { + variant "name as 'base'"; + variant "attribute"; +}; + + +type XSD.ID Id +with { + variant "name as uncapitalized"; + variant "attribute"; +}; + + +} +with { + encode "XML"; + variant "namespace as 'http://www.w3.org/XML/1998/namespace' prefix 'xml'"; + variant "controlNamespace 'http://www.w3.org/2001/XMLSchema-instance' prefix 'xsi'"; +} -- GitLab From 524df4ef9a2fed2c32c1d9166ebebdb51fa666ba Mon Sep 17 00:00:00 2001 From: garciay Date: Wed, 5 Jul 2023 14:26:25 +0200 Subject: [PATCH 27/37] Major bugs fixed in XML Signature --- ccsrc/security/src/certs_cache.cc | 6 +- ccsrc/security/src/security_externals.cc | 16 +++- ccsrc/security/src/securty_services.cc | 12 ++- .../ttcn/http_www_w3_org_2000_09_xmldsig.ttcn | 73 ++++++++++--------- 4 files changed, 64 insertions(+), 43 deletions(-) diff --git a/ccsrc/security/src/certs_cache.cc b/ccsrc/security/src/certs_cache.cc index 761fbb0..a6b8184 100644 --- a/ccsrc/security/src/certs_cache.cc +++ b/ccsrc/security/src/certs_cache.cc @@ -241,9 +241,8 @@ const std::string certs_cache::cert_to_string(const std::string& p_certificate_i int certs_cache::publickey_to_string(const EVP_PKEY* p_public_kep, std::vector& p_buffer) { loggers::get_instance().log(">>> certs_cache::publickey_to_string: '%p'", p_public_kep); - unsigned char buffer[512]; - unsigned char* ptr = &buffer[0]; - int ret = ::i2d_PublicKey((EVP_PKEY*)p_public_kep, &ptr); + unsigned char* buffer = nullptr; + int ret = ::i2d_PublicKey((EVP_PKEY*)p_public_kep, &buffer); loggers::get_instance().log("certs_cache::publickey_to_string: ret: '%d'", ret); if (ret < 0) { loggers::get_instance().warning("certs_cache::publickey_to_string: Failed to dunp certificate"); @@ -252,6 +251,7 @@ int certs_cache::publickey_to_string(const EVP_PKEY* p_public_kep, std::vector"); } // End of 'while'statement first = str.find(">", start); while ((first != -1) && (first < stop)) { //loggers::get_instance().log("transform_xslt_workaround: first='%d' ", first); - str = str.substr(0, first - 1) + ">" + str.substr(first + 1, str.length() - 1); + str = str.substr(0, first) + ">" + str.substr(first + 1, str.length() - 1); //loggers::get_instance().log("transform_xslt_workaround: New str (1): '%s'", str.c_str()); first = str.find(">", first); + stop = str.find(""); } // End of 'while'statement first = str.find("\"", start); while ((first != -1) && (first < stop)) { //loggers::get_instance().log("transform_xslt_workaround: first='%d' ", first); - str = str.substr(0, first - 1) + """ + str.substr(first + 1, str.length() - 1); + str = str.substr(0, first) + """ + str.substr(first + 1, str.length() - 1); //loggers::get_instance().log("transform_xslt_workaround: New str (1): '%s'", str.c_str()); first = str.find("\"", first); + stop = str.find(""); } // End of 'while'statement loggers::get_instance().log("<<< transform_xslt_workaround: '%s'", str.c_str()); @@ -176,6 +185,7 @@ INTEGER LibSecurity__Signature::fx__dec__xmldsig(BITSTRING& bs, http__www__w3__o std::string str(static_cast(oct2char(bit2oct(bs)))); loggers::get_instance().log("fx__dec__xmldsig: Before str: '%s'", str.c_str()); + transform_signature_workaround(str); transform_xslt_workaround(str); loggers::get_instance().log("fx__dec__xmldsig: Afer str: '%s'", str.c_str()); diff --git a/ccsrc/security/src/securty_services.cc b/ccsrc/security/src/securty_services.cc index 3c343f9..5d7bb7f 100644 --- a/ccsrc/security/src/securty_services.cc +++ b/ccsrc/security/src/securty_services.cc @@ -318,10 +318,20 @@ bool security_services::do_sign_verify(const CHARSTRING& p_message, const OCTETS } loggers::get_instance().log("security_services::do_sign_verify: public_key: '%p'", public_key); std::vector buffer; - _certs_db->publickey_to_string(public_key, buffer); + ret = _certs_db->publickey_to_string(public_key, buffer); + if (ret == 1) { + loggers::get_instance().warning("security_services::do_sign_verify: Failed to convert public key into string"); + return false; + } // Update the DigestValue + loggers::get_instance().log("security_services::do_sign_verify: canonicalized: '%s'", canonicalized.c_str()); int i = canonicalized.find(""); + if (i == std::string::npos) { + loggers::get_instance().warning("security_services::do_sign_verify: DigestValue entry not found"); + return false; + } + loggers::get_instance().log("security_services::do_sign_verify: i='%d'", i); canonicalized = canonicalized.substr(0, i + 13) + std::string(to64.cbegin(), to64.cend()) + canonicalized.substr(i + 13, canonicalized.length() - i - 13); OCTETSTRING to_be_signed(char2oct(CHARSTRING(canonicalized.c_str()))); loggers::get_instance().log_msg("security_services::do_sign_verify: to_be_signed: ", to_be_signed); diff --git a/ttcn/LibSecurity/ttcn/http_www_w3_org_2000_09_xmldsig.ttcn b/ttcn/LibSecurity/ttcn/http_www_w3_org_2000_09_xmldsig.ttcn index 5bea6b7..4be8b0b 100644 --- a/ttcn/LibSecurity/ttcn/http_www_w3_org_2000_09_xmldsig.ttcn +++ b/ttcn/LibSecurity/ttcn/http_www_w3_org_2000_09_xmldsig.ttcn @@ -18,10 +18,10 @@ // Contact: http://ttcn.ericsson.se // //////////////////////////////////////////////////////////////////////////////// -// Generated from file(s): -// - signature.xsd -// /* xml version = "1.0" encoding = "utf-8" */ -// /* targetnamespace = "http://www.w3.org/2000/09/xmldsig#" */ +// Generated from file(s): +// - signature.xsd +// /* xml version = "1.0" encoding = "utf-8" */ +// /* targetnamespace = "http://www.w3.org/2000/09/xmldsig#" */ //////////////////////////////////////////////////////////////////////////////// // Modification header(s): //----------------------------------------------------------------------------- @@ -40,37 +40,42 @@ import from XSD all; //import from http_www_cise_eu_sevicemodel_v1_message all; +type record Transform { + XSD.String algorithm, + XSD.String path +} +with { + variant "element"; + variant (algorithm) "name as capitalized"; + variant (algorithm) "attribute"; + variant (path) "untagged"; +} type record Signature { - record { - record { - XSD.String algorithm - } canonicalizationMethod, - record { - XSD.String algorithm - } signatureMethod, - record { - XSD.String uRI, - record { - record { - XSD.String algorithm, - XSD.String path - } transform - } transforms, - record { - XSD.String algorithm - } digestMethod, - XSD.String digestValue - } reference - } signedInfo, - XSD.String signatureValue, - record { - record { - XSD.String x509SubjectName, - XSD.String x509Certificate - } x509Data - } keyInfo + record { + record { + XSD.String algorithm + } canonicalizationMethod, + record { + XSD.String algorithm + } signatureMethod, + record { + XSD.String uRI, + record of Transform transforms, + record { + XSD.String algorithm + } digestMethod, + XSD.String digestValue + } reference + } signedInfo, + XSD.String signatureValue, + record { + record { + XSD.String x509SubjectName, + XSD.String x509Certificate + } x509Data + } keyInfo } with { variant "element"; @@ -85,10 +90,6 @@ with { variant (signedInfo.reference.uRI) "name as capitalized"; variant (signedInfo.reference.uRI) "attribute"; variant (signedInfo.reference.transforms) "name as capitalized"; - variant (signedInfo.reference.transforms.transform) "name as capitalized"; - variant (signedInfo.reference.transforms.transform.algorithm) "name as capitalized"; - variant (signedInfo.reference.transforms.transform.algorithm) "attribute"; - variant (signedInfo.reference.transforms.transform.path) "untagged"; variant (signedInfo.reference.digestMethod) "name as capitalized"; variant (signedInfo.reference.digestMethod.algorithm) "name as capitalized"; variant (signedInfo.reference.digestMethod.algorithm) "attribute"; -- GitLab From c7b208ea9b477564472cf523f6000ed1e43000cf Mon Sep 17 00:00:00 2001 From: garciay Date: Mon, 28 Aug 2023 16:48:29 +0200 Subject: [PATCH 28/37] Finalyze Security TCs --- ccsrc/security/src/securty_services.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ccsrc/security/src/securty_services.cc b/ccsrc/security/src/securty_services.cc index 5d7bb7f..e6d0acb 100644 --- a/ccsrc/security/src/securty_services.cc +++ b/ccsrc/security/src/securty_services.cc @@ -135,7 +135,7 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const OCTET to64 = converter::get_instance().buffer_to_base64(std::vector(static_cast(to_be_signed), to_be_signed.lengthof() + static_cast(to_be_signed))); loggers::get_instance().log("security_services::do_sign: Data to be signed/verified: '%s'", converter::get_instance().bytes_to_string(to64).c_str()); - // Retrive the private key + // Retrieve the private key const EVP_PKEY* private_key; int ret = _certs_db->get_private_key(certificate_id, &private_key); if (ret == 1) { @@ -183,7 +183,7 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const OCTET ::EVP_MD_CTX_free(ctx); // // Ensure that the signature round-trips - // // Retrive the public key + // // Retrieve the public key // const EVP_PKEY* public_key; // if (_certs_db->get_private_key(certificate_id, &public_key) == 1) { // loggers::get_instance().warning("security_services::do_sign: Failed to retrieve private key"); @@ -309,7 +309,7 @@ bool security_services::do_sign_verify(const CHARSTRING& p_message, const OCTETS } loggers::get_instance().log("security_services::do_sign_verify: certificate dump: '%s'", _certs_db->cert_to_string(certificate_id).c_str()); - // Retrive the public key + // Retrieve the public key const EVP_PKEY* public_key; int ret = _certs_db->get_public_keys(certificate_id, &public_key); if (ret == 1) { -- GitLab From c38a2f267cb659c8180548bc82721d34dc71ef85 Mon Sep 17 00:00:00 2001 From: garciay Date: Fri, 8 Sep 2023 16:39:50 +0200 Subject: [PATCH 29/37] Adding new TCs for I1 --- ccsrc/Helpers/helpers_externals.cc | 22 ++++++++++++++++++- ccsrc/security/src/certs_cache.cc | 15 ++++++++----- ccsrc/security/src/certs_loader.cc | 5 ++++- .../LibHelpers/ttcn/LibHelpers_Functions.ttcn | 2 +- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/ccsrc/Helpers/helpers_externals.cc b/ccsrc/Helpers/helpers_externals.cc index c9f2ec7..37d1f3e 100644 --- a/ccsrc/Helpers/helpers_externals.cc +++ b/ccsrc/Helpers/helpers_externals.cc @@ -121,7 +121,27 @@ namespace LibHelpers__Functions { * @brief Retrieve the current local date/time formatted as yyyy-mm-ddThh:mm:ss.lll+nn:00 * @return The the current date/time on success, a null string otherwise */ - CHARSTRING fx__get__current__date__time() { //2018-01-18T13:19:35.367+01:00 + CHARSTRING fx__get__current__date__time(const INTEGER& p__shift__time) { //2018-01-18T13:19:35.367+01:00 + loggers::get_instance().log(">>> fx__get__current__date__time"); + + time_t t = std::time(nullptr); + if (p__shift__time != 0) { + t += static_cast(p__shift__time); + } + auto tm = *std::localtime(&t); + std::ostringstream oss; + oss << std::put_time(&tm, "%FT%TZ");//%FT%T%Z + + CHARSTRING dt(oss.str().c_str()); + loggers::get_instance().log_msg("fx__get__current__date__time: ", dt); + return dt; + } + + /** + * @brief Retrieve the local date/time in the past formatted as yyyy-mm-ddThh:mm:ss.lll+nn:00 + * @return The the current date/time on success, a null string otherwise + */ + CHARSTRING fx__get__current__date__time__past() { //2018-01-18T13:19:35.367+01:00 loggers::get_instance().log(">>> fx__get__current__date__time"); time_t t = std::time(nullptr); diff --git a/ccsrc/security/src/certs_cache.cc b/ccsrc/security/src/certs_cache.cc index a6b8184..1d7bcf7 100644 --- a/ccsrc/security/src/certs_cache.cc +++ b/ccsrc/security/src/certs_cache.cc @@ -183,9 +183,13 @@ int certs_cache::store_certificate(const std::string& p_certificate_name, const loggers::get_instance().log(">>> certs_cache::store_certificate: '%s'", p_certificate_name.c_str()); if (certs_loader::get_instance().store_certificate(p_certificate_name, p_certificate_pem, p_certificate_id, _certificates) == -1) { - loggers::get_instance().warning("certs_cache::store_certificate: Failed to load certificate"); - return -1; - } + loggers::get_instance().warning("certs_cache::store_certificate: Failed to load certificate"); + return -1; + } + + loggers::get_instance().log("certs_cache::store_certificate: Dump of current certificates: "); + dump(); + // Certificate is on the DB, load it std::map>::const_iterator it = _certificates.find(p_certificate_id); *p_record = it->second.get(); @@ -194,17 +198,18 @@ int certs_cache::store_certificate(const std::string& p_certificate_name, const std::string sn(256, (char)0x00); const X509_NAME* subject = (*p_record)->subject_name(); ::X509_NAME_oneline(subject, sn.data(), sn.length()); - loggers::get_instance().log("certs_cache::store_certificate: sn: '%s'", sn.c_str()); + loggers::get_instance().log("certs_cache::store_certificate: sn: '%s'", sn.c_str()); _certificates_subject.insert(std::pair(sn, p_certificate_id)); return 0; } void certs_cache::dump() const { - loggers::get_instance().log("certs_cache::dump_certificates: # items = %d", _certificates.size()); + loggers::get_instance().log(">>> certs_cache::dump_certificates: # items = %d", _certificates.size()); for (std::map>::const_iterator it = _certificates.cbegin(); it != _certificates.cend(); ++it) { const certs_db_record *p = it->second.get(); + loggers::get_instance().log("certs_cache::dump_certificates: certificate_id: '%s'", p->certificate_id().c_str()); } // End of 'for' statement } // End of method dump diff --git a/ccsrc/security/src/certs_loader.cc b/ccsrc/security/src/certs_loader.cc index 91bd87b..306e6a5 100644 --- a/ccsrc/security/src/certs_loader.cc +++ b/ccsrc/security/src/certs_loader.cc @@ -210,6 +210,10 @@ int certs_loader::store_certificate(const std::string& p_certificate_name, const loggers::get_instance().log("certs_loader::store_certificate: p_certificate_id: '%s'", p_certificate_id.c_str()); loggers::get_instance().log("certs_loader::store_certificate: cert: '%p'", cert); + + // FIXME Dump certificate + + // Create new record certs_db_record *r = new certs_db_record(p_certificate_name, cert, nullptr, p_certificate_pem); std::pair>::iterator, bool> result = p_certificates.insert(std::pair>(p_certificate_id, std::unique_ptr(r))); @@ -221,4 +225,3 @@ int certs_loader::store_certificate(const std::string& p_certificate_name, const return 0; } // End of method store_certificate - diff --git a/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn b/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn index f7edf96..1f93d1c 100644 --- a/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn +++ b/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn @@ -178,7 +178,7 @@ module LibHelpers_Functions { */ external function fx_generate_uuid() return charstring; - external function fx_get_current_date_time() return charstring; + external function fx_get_current_date_time(in integer p_shift_time) return charstring; } // End of externals -- GitLab From e27aaa847f49a1e459f427abc3620ef7a40223ca Mon Sep 17 00:00:00 2001 From: garciay Date: Tue, 26 Sep 2023 08:40:33 +0200 Subject: [PATCH 30/37] Add params local_server --- ccsrc/Framework/include/params.hh | 5 +++-- ccsrc/Framework/src/params.cc | 1 + ccsrc/Protocols/Tcp/tcp_layer.cc | 17 +++++++++++++---- ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn | 9 +++++---- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/ccsrc/Framework/include/params.hh b/ccsrc/Framework/include/params.hh index 6bb5dcd..bc683cf 100644 --- a/ccsrc/Framework/include/params.hh +++ b/ccsrc/Framework/include/params.hh @@ -35,14 +35,15 @@ public: //! \publicsection static const std::string& nic; //! Network Interface Card parameter name - static const std::string& server; //! HTTP server address (e.g. www.etsi.org) - static const std::string& port; //! HTTP server port. Default: 80 + static const std::string& server; //! Remote server address (e.g. www.etsi.org) + static const std::string& port; //! Remote server port. Default: 80 static const std::string& use_ssl; //! Set to 1 to use SSL to communicate with the HTTP server. Default: false static const std::string& mutual_auth; //! Set to 1 to use mutual authentication. Default: false static const std::string& trusted_ca_list; //! List of trusted CA certificates static const std::string& certificate; //! Chain of certificates static const std::string& privkey; //! Certificate private key static const std::string& server_mode; //! Does the test sytem acting as a server. Default: 0 + static const std::string& local_server; //! Local server address (e.g. localhost) static const std::string& local_port; //! Local listener port. Default: 80 static const std::string& method; //! HTTP method type. Default: POST diff --git a/ccsrc/Framework/src/params.cc b/ccsrc/Framework/src/params.cc index d58d39a..a183714 100644 --- a/ccsrc/Framework/src/params.cc +++ b/ccsrc/Framework/src/params.cc @@ -37,6 +37,7 @@ const std::string& params::certificate = std::string("certificate"); const std::string& params::privkey = std::string("privkey"); const std::string& params::server_mode = std::string("server_mode"); +const std::string& params::local_server = std::string("local_server"); const std::string& params::local_port = std::string("local_port"); const std::string& params::method = std::string("method"); diff --git a/ccsrc/Protocols/Tcp/tcp_layer.cc b/ccsrc/Protocols/Tcp/tcp_layer.cc index fdbeb35..2c49ef9 100644 --- a/ccsrc/Protocols/Tcp/tcp_layer.cc +++ b/ccsrc/Protocols/Tcp/tcp_layer.cc @@ -51,8 +51,8 @@ void tcp_layer::init() { if (it == _params.cend()) { _params.insert(std::pair(std::string("server"), "127.0.0.1")); // TODO Try using params::server instead of std::string("server") } - if (!parameter_set(params::server.c_str(), _params[params::server].c_str())) { - loggers::get_instance().warning("tcp_layer::set_parameter: Unprocessed parameter: '%s'", params::server.c_str()); + if (!parameter_set(remote_address_name(), _params[params::server].c_str())) { + loggers::get_instance().warning("tcp_layer::set_parameter: Unprocessed parameter: 'remote_address_name()'"); } bool ssl_mode = false; it = _params.find(params::use_ssl); @@ -86,13 +86,22 @@ void tcp_layer::init() { loggers::get_instance().warning("tcp_layer::set_parameter: Unprocessed parameter: '%s'", params::local_port.c_str()); } + it = _params.find(params::local_server); + if (it == _params.cend()) { + _params.insert(std::pair(std::string("local_server"), "0.0.0.0")); + } + if (!parameter_set(local_address_name(), _params[params::local_server].c_str())) { + loggers::get_instance().warning("tcp_layer::set_parameter: Unprocessed parameter: '%s'", params::local_server.c_str()); + } + parameter_set(use_connection_ASPs_name(), (!server_mode) ? "yes" : "no"); loggers::get_instance().warning("tcp_layer::set_parameter: Limit to one simultanneous accepted connection (server_backlog == 1)"); parameter_set(server_backlog_name(), "1"); // Limit to one simultanneous accepted connection loggers::get_instance().log("tcp_layer::init: server_mode=%x", server_mode); set_server_mode(server_mode); - if (server_mode) { - parameter_set("serverPort", _params[params::local_port].c_str()); + if (server_mode) { // Apply default values or specified ones + parameter_set(local_port_name(), _params[params::local_port].c_str()); + parameter_set(local_address_name(), _params[params::local_server].c_str()); } if (ssl_mode) { // Add certificate bundle // Check mutual authentication param diff --git a/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn b/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn index 1f93d1c..90253cd 100644 --- a/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn +++ b/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn @@ -25,12 +25,13 @@ module LibHelpers_Functions { * @return random integer * */ - function f_random( in integer p_lowerbound, - in integer p_upperbound ) - return integer { + function f_random( + in integer p_lowerbound, + in integer p_upperbound + ) return integer { //Variables var integer v_random := 0; - v_random := float2int(int2float(p_upperbound - p_lowerbound +1)*rnd()) + p_lowerbound; + v_random := float2int(int2float(p_upperbound - p_lowerbound + 1) * rnd()) + p_lowerbound; log("*** f_random: INFO: OK - random value = " & int2str(v_random) & " ***"); return v_random; -- GitLab From f69933a762635155275283e4f8594f0f3aff9a24 Mon Sep 17 00:00:00 2001 From: garciay Date: Mon, 11 Dec 2023 08:50:16 +0100 Subject: [PATCH 31/37] STF 637: Workaroud on XML transform. To be enhanced using libxslt-dev - see opened issues --- ccsrc/Protocols/Xml/src/xml_converters.cc | 56 ++++++++++++++++++- ccsrc/security/src/securty_services.cc | 3 +- .../LibHelpers/ttcn/LibHelpers_Functions.ttcn | 23 +++++--- ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn | 8 +-- 4 files changed, 73 insertions(+), 17 deletions(-) diff --git a/ccsrc/Protocols/Xml/src/xml_converters.cc b/ccsrc/Protocols/Xml/src/xml_converters.cc index 4f47eea..ef98233 100644 --- a/ccsrc/Protocols/Xml/src/xml_converters.cc +++ b/ccsrc/Protocols/Xml/src/xml_converters.cc @@ -75,10 +75,60 @@ int xml_converters::xml_transform(const std::string& p_to_transform, std::string } // End of 'while'statement // - first = p_transformed.find("", first + 8 + 1); - p_transformed = p_transformed.substr(0, first + 8) + p_transformed.substr(next + 1, p_transformed.length() - next - 1); + next = p_transformed.find("\">", first + l + 1); + loggers::get_instance().log("xml_converters::xml_transform: New p_transformed (3): '%s'", p_transformed.c_str()); + p_transformed = p_transformed.substr(0, first + l) + p_transformed.substr(next + 1, p_transformed.length() - next - 1); + } + // + first = p_transformed.find("", first + l + 1); + loggers::get_instance().log("xml_converters::xml_transform: New p_transformed (4): '%s'", p_transformed.c_str()); + p_transformed = p_transformed.substr(0, first + l) + p_transformed.substr(next + 1, p_transformed.length() - next - 1); + } + // + first = p_transformed.find("", first + l + 1); + loggers::get_instance().log("xml_converters::xml_transform: New p_transformed (5): '%s'", p_transformed.c_str()); + p_transformed = p_transformed.substr(0, first + l) + p_transformed.substr(next + 1, p_transformed.length() - next - 1); + } + // + first = p_transformed.find("", first + l + 1); + loggers::get_instance().log("xml_converters::xml_transform: New p_transformed (6): '%s'", p_transformed.c_str()); + p_transformed = p_transformed.substr(0, first + l) + p_transformed.substr(next + 1, p_transformed.length() - next - 1); + } + // + first = p_transformed.find("", first + l + 1); + loggers::get_instance().log("xml_converters::xml_transform: New p_transformed (7): '%s'", p_transformed.c_str()); + p_transformed = p_transformed.substr(0, first + l) + p_transformed.substr(next + 1, p_transformed.length() - next - 1); + } + // + first = p_transformed.find("", first + l + 1); + loggers::get_instance().log("xml_converters::xml_transform: New p_transformed (8): '%s'", p_transformed.c_str()); + p_transformed = p_transformed.substr(0, first + l) + p_transformed.substr(next + 1, p_transformed.length() - next - 1); + } + // + first = p_transformed.find("", first + l + 1); + loggers::get_instance().log("xml_converters::xml_transform: New p_transformed (8): '%s'", p_transformed.c_str()); + p_transformed = p_transformed.substr(0, first + l) + p_transformed.substr(next + 1, p_transformed.length() - next - 1); } loggers::get_instance().log("<<< xml_converters::xml_transform: '%s'", p_transformed.c_str()); diff --git a/ccsrc/security/src/securty_services.cc b/ccsrc/security/src/securty_services.cc index e6d0acb..eb459f6 100644 --- a/ccsrc/security/src/securty_services.cc +++ b/ccsrc/security/src/securty_services.cc @@ -50,10 +50,11 @@ int security_services::do_sign(const OCTETSTRING& p_encoded_message, const OCTET // Transform: Remove all CR, LS, TAB and SPACE outside of the tags std::string transformed; xml_converters::get_instance().xml_transform(std::string((const char*)(static_cast(p_encoded_message)), p_encoded_message.lengthof()), transformed); - loggers::get_instance().log("security_services::do_sign: p_pull_request_transormed: ", transformed.c_str()); + loggers::get_instance().log("security_services::do_sign: p_pull_request_transormed: '%s'", transformed.c_str()); // Canonicalization std::string canonicalized; xml_converters::get_instance().xml_canonicalization(transformed, canonicalized); + loggers::get_instance().log("security_services::do_sign: canonicalized: '%s'", canonicalized.c_str()); p_pull_request_canonicalized = CHARSTRING(canonicalized.c_str()); OCTETSTRING encoded_message(char2oct(p_pull_request_canonicalized)); loggers::get_instance().log_msg("security_services::do_sign: p_pull_request_canonicalized: ", p_pull_request_canonicalized); diff --git a/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn b/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn index 90253cd..32711d8 100644 --- a/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn +++ b/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn @@ -162,23 +162,28 @@ module LibHelpers_Functions { external function fx_getDSecond() return UInt16; /** - * @desc Encode into Base64 - * @return p_to_encode - The buffer to be encoded - */ + * @desc Encode into Base64 + * @return p_to_encode - The buffer to be encoded + */ external function fx_enc_base64(in octetstring p_to_encode) return octetstring; /** - * @desc Decode from Base64 - * @return p_to_decode - The buffer to be decoded - */ + * @desc Decode from Base64 + * @return p_to_decode - The buffer to be decoded + */ external function fx_dec_base64(in octetstring p_to_decode) return octetstring; /** - * @desc Generate a new UUID - * @return The UUID in string format on success, a null string otherwise - */ + * @desc Generate a new UUID + * @return The UUID in string format on success, a null string otherwise + */ external function fx_generate_uuid() return charstring; + /** + * @brief Retrieve the current local date/time formatted as yyyy-mm-ddThh:mm:ss.lll+nn:00 + * @param p_shift_time The algebric number of seconds to add to the current time + * @return The the current date/time on success, a null string otherwise + */ external function fx_get_current_date_time(in integer p_shift_time) return charstring; } // End of externals diff --git a/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn b/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn index fc641a2..8bbfa1e 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn @@ -366,13 +366,13 @@ module LibHttp_Templates { group http_html_body { template (value) HttpMessageBody m_http_message_body_html( - in template (value) HtmlBody p_html_body + in template (value) HtmlBody p_html_body ) := { html_body := p_html_body } // End of template m_http_message_body_html template (present) HttpMessageBody mw_http_message_body_html( - template (present) HtmlBody p_html_body := ? + template (present) HtmlBody p_html_body := ? ) := { html_body := p_html_body } // End of template mw_http_message_body_html @@ -398,13 +398,13 @@ module LibHttp_Templates { group http_json_body { template (value) HttpMessageBody m_http_message_body_json( - in template (value) JsonBody p_json_body + in template (value) JsonBody p_json_body ) := { json_body := p_json_body } // End of template m_http_message_body_json template (present) HttpMessageBody mw_http_message_body_json( - template (present) JsonBody p_json_body := ? + template (present) JsonBody p_json_body := ? ) := { json_body := p_json_body } // End of template mw_http_message_body_json -- GitLab From eb652d4fbd09a333332d4e2fb28aede6543d456b Mon Sep 17 00:00:00 2001 From: garciay Date: Tue, 12 Dec 2023 17:28:56 +0100 Subject: [PATCH 32/37] Add support of unzip BFK AT download --- ccsrc/Protocols/Http/http_codec.cc | 65 +++++++++++++++++++++++++----- ccsrc/Protocols/Http/http_codec.hh | 6 ++- ccsrc/Protocols/Http/http_layer.cc | 7 +++- ccsrc/Protocols/Tcp/tcp_layer.cc | 4 ++ 4 files changed, 71 insertions(+), 11 deletions(-) diff --git a/ccsrc/Protocols/Http/http_codec.cc b/ccsrc/Protocols/Http/http_codec.cc index 270c6c1..cdf4ab7 100644 --- a/ccsrc/Protocols/Http/http_codec.cc +++ b/ccsrc/Protocols/Http/http_codec.cc @@ -41,20 +41,47 @@ int http_codec::encode(const LibHttp__TypesAndValues::HttpMessage &msg, OCTETSTR int http_codec::decode(const OCTETSTRING &data, LibHttp__TypesAndValues::HttpMessage &msg, params *params) { loggers::get_instance().log_msg(">>> http_codec::decode: data=", data); - // Sanity checks - if ((data[0].get_octet() & 0x80) == 0x80) { - loggers::get_instance().warning("http_codec::decode: Unicode format not supported"); - return -1; - } - TTCN_EncDec::clear_error(); - TTCN_Buffer decoding_buffer(data); - loggers::get_instance().log_to_hexa("http_codec::decode: decoding_buffer=", decoding_buffer); + TTCN_Buffer decoding_buffer; + + if (_initial_content_length != 0) { // Check if the data is a new fragment of the response + loggers::get_instance().warning("http_codec::decode: Need to bufferize and wait for all fragments received"); + _bufferized_buffers.push_back(data); + _current_content_length += data.lengthof(); // FIXME Need to calculate the size of the header buffer, do not assume th first fragmwnt is the header buffer + loggers::get_instance().log("http_codec::decode: _bufferized_buffers size: %d - _current_content_length: %d - _initial_content_length: %d", _bufferized_buffers.size(), _current_content_length, _initial_content_length); + if (_current_content_length < _initial_content_length) { // Wait for the next fragment + loggers::get_instance().warning("http_codec::decode: Wait for the next fragment"); + return -2; + } else { // Rebuild the wall message and continue the decoding + loggers::get_instance().log("http_codec::decode: All the fragments were received, rebuild message"); + // Concatenate the fragments + loggers::get_instance().log("http_codec::decode: Concatenate bufferized datas"); + for (size_t i = 0; i < _bufferized_buffers.size(); i++) { + decoding_buffer.put_string(_bufferized_buffers[i]); + } // End of 'for' statement + _bufferized_buffers.clear(); + loggers::get_instance().log("http_codec::decode: _bufferized_buffers cleared: %d", _bufferized_buffers.size()); + // Reset counters + loggers::get_instance().log("http_codec::decode: Reset bufferization counters"); + _initial_content_length = 0; + _current_content_length = 0; + // Continue the decoding + } + } else { // It can be a full HTTP response or the first gragment of the HTTP response + decoding_buffer.put_string(data); + } + loggers::get_instance().log("http_codec::decode: decoding_buffer size: %d", decoding_buffer.get_len()); + loggers::get_instance().log_to_hexa("http_codec::decode: Before decoding_buffer Body: ", decoding_buffer); _dc.reset(); _params = params; + if ((*decoding_buffer.get_data() & 0x80) == 0x80) { + loggers::get_instance().warning("http_codec::decode: Unicode format not supported"); + return -1; + } + // Get the first line (e.g. HTTP/1.1 302 Found or POST / HTTP/1.1) CHARSTRING message_id; if (get_line(decoding_buffer, message_id) == -1) { @@ -84,10 +111,30 @@ int http_codec::decode(const OCTETSTRING &data, LibHttp__TypesAndValues::HttpMes response.statuscode() = std::stoi(m[3].str().c_str()); response.statustext() = CHARSTRING(m[4].str().c_str()); LibHttp__TypesAndValues::Headers headers; - std::string content_type; + std::string content_type; decode_headers(decoding_buffer, headers, content_type); + if (_dc.length > decoding_buffer.get_len()) { // HTTP response is fragmented + // Need to bufferize the first packet and wait for the other fragments tp be received + loggers::get_instance().warning("http_codec::decode: Need to bufferize the first packet and wait for the other fragments tp be received"); + // Set counters + loggers::get_instance().log("http_codec::decode: Set bufferization counters"); + _initial_content_length = _dc.length; + _current_content_length = 0; + _bufferized_buffers.push_back(data); + _current_content_length += data.lengthof(); + loggers::get_instance().log("http_codec::decode: _bufferized_buffers size: %d - _current_content_length: %d", _bufferized_buffers.size(), _current_content_length); + return -2; + } else { + // Force reset counters + loggers::get_instance().log("http_codec::decode: Force reset bufferization counters"); + _initial_content_length = 0; + _current_content_length = 0; + } + response.header() = headers; loggers::get_instance().log_to_hexa("Before decoding Body: ", decoding_buffer); + loggers::get_instance().log("http_codec::decode: _initial_content_length = %d", _initial_content_length); + loggers::get_instance().log("http_codec::decode: headers().content_length (_dc.length) = %d - decoding_buffer.get_len() = %d", _dc.length, decoding_buffer.get_len()); LibHttp__MessageBodyTypes::HttpMessageBody body; if (decode_body(decoding_buffer, body, content_type) == -1) { response.body().set_to_omit(); diff --git a/ccsrc/Protocols/Http/http_codec.hh b/ccsrc/Protocols/Http/http_codec.hh index 04079e6..37f313c 100644 --- a/ccsrc/Protocols/Http/http_codec.hh +++ b/ccsrc/Protocols/Http/http_codec.hh @@ -9,6 +9,7 @@ class Base_Type; class Record_Type; class TTCN_Typedescriptor_t; class TTCN_Buffer; +class OCTETSTRING; namespace LibHttp__TypesAndValues { class HttpMessage; @@ -60,9 +61,12 @@ class http_codec : public codec_gen>> _codecs; + std::vector _bufferized_buffers; + unsigned int _initial_content_length; + unsigned int _current_content_length; public: - explicit http_codec() : codec_gen(), _ec(), _dc(), _codecs(){}; + explicit http_codec() : codec_gen(), _ec(), _dc(), _codecs(), _bufferized_buffers(), _initial_content_length{0}, _current_content_length{0} {}; virtual ~http_codec(){}; virtual int encode(const LibHttp__TypesAndValues::HttpMessage &, OCTETSTRING &data); diff --git a/ccsrc/Protocols/Http/http_layer.cc b/ccsrc/Protocols/Http/http_layer.cc index bf4da9f..8d83cbc 100644 --- a/ccsrc/Protocols/Http/http_layer.cc +++ b/ccsrc/Protocols/Http/http_layer.cc @@ -95,9 +95,14 @@ void http_layer::receive_data(OCTETSTRING &data, params ¶ms) { // Decode HTTP message LibHttp__TypesAndValues::HttpMessage http_message; - if (_codec->decode(data, http_message, ¶ms) == -1) { + int ret_code = _codec->decode(data, http_message, ¶ms); + if (ret_code == -1) { loggers::get_instance().warning("http_layer::receive_data: Failed to decode data"); return; + } else if (ret_code == -2) { // Need to wait for next data + loggers::get_instance().log("http_layer::receive_data: Set Buffurizing to 1"); + params.insert(std::make_pair("Buffurizing", "1")); + return; } if (_device_mode) { OCTETSTRING os; diff --git a/ccsrc/Protocols/Tcp/tcp_layer.cc b/ccsrc/Protocols/Tcp/tcp_layer.cc index 2c49ef9..632ec3b 100644 --- a/ccsrc/Protocols/Tcp/tcp_layer.cc +++ b/ccsrc/Protocols/Tcp/tcp_layer.cc @@ -210,6 +210,10 @@ void tcp_layer::message_incoming(const unsigned char* message_buffer, int length std::string("timestamp"), std::to_string(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()))); this->receive_data(data, params); // TODO Check execution time for decoding operation + params::const_iterator it = params.find(std::string("Buffurizing")); + if (it != params.end()) { + loggers::get_instance().log("tcp_layer::message_incoming: Buffurizing requested"); + } loggers::get_instance().set_stop_time(_time_key, duration); } -- GitLab From 6901c1c381950f308d2b1643e90757248ae99eab Mon Sep 17 00:00:00 2001 From: garciay Date: Mon, 18 Dec 2023 08:07:46 +0100 Subject: [PATCH 33/37] Editorial changes --- ttcn/LibHttp/ttcn/LibHttp_Functions.ttcn | 10 +++++----- ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn | 8 ++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/ttcn/LibHttp/ttcn/LibHttp_Functions.ttcn b/ttcn/LibHttp/ttcn/LibHttp_Functions.ttcn index 3a4e457..73b9791 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_Functions.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_Functions.ttcn @@ -193,7 +193,7 @@ module LibHttp_Functions { in Headers p_headers, in charstring p_header_name := c_header_content_text, out charstring_list p_header_value - ) { + ) { // Sanity checks if (lengthof(p_header_name) == 0) { return; @@ -216,10 +216,10 @@ module LibHttp_Functions { * @return true on success, false otherwise */ function f_check_headers( - in Headers p_headers, - in charstring p_header_name := "Location", - in template (present) charstring p_value := ? - ) return boolean { + in Headers p_headers, + in charstring p_header_name := "Location", + in template (present) charstring p_value := ? + ) return boolean { // Local variables var boolean v_header_matched := false; diff --git a/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn b/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn index 8bbfa1e..9a9d42a 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn @@ -353,6 +353,14 @@ module LibHttp_Templates { statustext := "Not Found" } // End of template mw_http_response_404_not_found + template Response mw_http_response_405_not_applicable( + template HttpMessageBody p_body := *, + template (present) Headers p_header := ? + ) modifies mw_http_response_ko := { + statuscode := 405, + statustext := "Not Applicable" + } // End of template mw_http_response_405_not_applicable + template Response mw_http_response_412_precondition_failed( template HttpMessageBody p_body := *, template (present) Headers p_header := ? -- GitLab From 7d4fc3323e831d6d07fcf8cd2cf2c5303384a6c6 Mon Sep 17 00:00:00 2001 From: garciay Date: Sun, 10 Mar 2024 15:02:50 +0100 Subject: [PATCH 34/37] Bug fixed in HTTP codec when Content-Length is no present --- ccsrc/Protocols/Http/http_codec.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ccsrc/Protocols/Http/http_codec.cc b/ccsrc/Protocols/Http/http_codec.cc index cdf4ab7..c0fac4c 100644 --- a/ccsrc/Protocols/Http/http_codec.cc +++ b/ccsrc/Protocols/Http/http_codec.cc @@ -113,6 +113,8 @@ int http_codec::decode(const OCTETSTRING &data, LibHttp__TypesAndValues::HttpMes LibHttp__TypesAndValues::Headers headers; std::string content_type; decode_headers(decoding_buffer, headers, content_type); + loggers::get_instance().log("http_codec::decode: _dc.length=%d", _dc.length); + loggers::get_instance().log("http_codec::decode: decoding_buffer.get_len()=%d", decoding_buffer.get_len()); if (_dc.length > decoding_buffer.get_len()) { // HTTP response is fragmented // Need to bufferize the first packet and wait for the other fragments tp be received loggers::get_instance().warning("http_codec::decode: Need to bufferize the first packet and wait for the other fragments tp be received"); @@ -417,8 +419,12 @@ int http_codec::decode_headers(TTCN_Buffer &decoding_buffer, LibHttp__TypesAndVa } break; case 1: if (headers.is_bound()) { - loggers::get_instance().log_msg("<<< http_codec::decode_headers: ", headers); - return 0; + if (_dc.length == -1) { // content-Length header not found, force length to 0, assuming no body is present + loggers::get_instance().log("http_codec::decode_headers: Force _dc.length to 0"); + _dc.length = 0; + } + loggers::get_instance().log_msg("<<< http_codec::decode_headers: ", headers); + return 0; } else { loggers::get_instance().warning("http_codec::decode_headers: Failed to decode headers"); return -1; @@ -431,7 +437,7 @@ int http_codec::decode_headers(TTCN_Buffer &decoding_buffer, LibHttp__TypesAndVa } int http_codec::decode_header(CHARSTRING &header_line, LibHttp__TypesAndValues::Header &header) { - loggers::get_instance().log_msg(">>> http_codec::decode_header", header_line); + loggers::get_instance().log_msg(">>> http_codec::decode_header: ", header_line); try { std::string str(static_cast(header_line)); -- GitLab From 6959b8be419f3755de6f888e24bfdc8de07383a7 Mon Sep 17 00:00:00 2001 From: garciay Date: Thu, 21 Mar 2024 12:10:36 +0100 Subject: [PATCH 35/37] Remove useless whitespaces/tab --- .../LibHelpers/ttcn/LibHelpers_Functions.ttcn | 46 +++---- .../ttcn/LibHttp_BinaryMessageBodyTypes.ttcn | 2 +- ttcn/LibHttp/ttcn/LibHttp_BinaryTypes.ttcn | 4 +- .../ttcn/LibHttp_EncdecDeclarations.ttcn | 6 +- ttcn/LibHttp/ttcn/LibHttp_Functions.ttcn | 86 ++++++------ ttcn/LibHttp/ttcn/LibHttp_JSONTypes.ttcn | 4 +- .../ttcn/LibHttp_JsonMessageBodyTypes.ttcn | 6 +- ttcn/LibHttp/ttcn/LibHttp_JsonTemplates.ttcn | 8 +- .../ttcn/LibHttp_MessageBodyTypes.ttcn | 10 +- ttcn/LibHttp/ttcn/LibHttp_Pics.ttcn | 12 +- ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn | 124 +++++++++--------- ttcn/LibHttp/ttcn/LibHttp_TestSystem.ttcn | 12 +- ttcn/LibHttp/ttcn/LibHttp_TypesAndValues.ttcn | 18 +-- ttcn/LibHttp/ttcn/LibHttp_XMLTypes.ttcn | 6 +- .../ttcn/LibHttp_XmlMessageBodyTypes.ttcn | 8 +- ttcn/LibHttp/ttcn/LibHttp_XmlTemplates.ttcn | 10 +- ttcn/LibJson/ttcn/Json.ttcn | 6 +- .../http_www_w3_org_XML_1998_namespace.ttcn | 4 +- 18 files changed, 186 insertions(+), 186 deletions(-) diff --git a/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn b/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn index 32711d8..b5c6bd5 100644 --- a/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn +++ b/ttcn/LibHelpers/ttcn/LibHelpers_Functions.ttcn @@ -9,14 +9,14 @@ * All rights reserved. * */ - + module LibHelpers_Functions { // LibCommon import from LibCommon_BasicTypesAndValues all; - + group math { - + /** * @desc function to generate integer random values * @see ttcn-3 - rnd() @@ -32,10 +32,10 @@ module LibHelpers_Functions { //Variables var integer v_random := 0; v_random := float2int(int2float(p_upperbound - p_lowerbound + 1) * rnd()) + p_lowerbound; - + log("*** f_random: INFO: OK - random value = " & int2str(v_random) & " ***"); return v_random; - + } // End of function f_random /** @@ -45,7 +45,7 @@ module LibHelpers_Functions { */ function f_abs(in integer p_number) return integer { - + if(p_number < 0) { return 0 - p_number; } @@ -59,7 +59,7 @@ module LibHelpers_Functions { */ function ff_abs(in float p_number) return float { - + if(p_number < 0.0) { return 0.0 - p_number; } @@ -74,7 +74,7 @@ module LibHelpers_Functions { */ function f_min(in integer p_a, in integer p_b) return integer { - + if(p_a < p_b) { return p_a; } @@ -91,7 +91,7 @@ module LibHelpers_Functions { function f_removeUnsignificantBits(in bitstring p_bitstring) return bitstring { var integer i, len; - + len := lengthof(p_bitstring); for(i:=len-1; i >=0 and p_bitstring[i] == '0'B; i:=i-1) {} return substr(p_bitstring, 0, i + 1); @@ -106,61 +106,61 @@ module LibHelpers_Functions { */ function f_getCurrentTimeUtc() return UInt64 { var UInt64 v_time := 0; - + // log("*** f_getCurrentTimeUtc: INFO: calling fx_getCurrentTimeUtc() ***"); v_time := fx_getCurrentTimeUtc(); - + return v_time; } - + /** * @desc Gets the Minute of current UTC year * @return MinuteOfTheYear - tenths of a second in the current or next hour in units of 1/10th second from UTC time */ function f_getMinuteOfTheYear() return UInt16 { var UInt16 v_minuteOfTheYear := 0; - + // log("*** f_getMinuteOfTheYear: INFO: calling fx_getMinuteOfTheYear() ***"); v_minuteOfTheYear := fx_getMinuteOfTheYear(); - + return v_minuteOfTheYear; } - + /** * @desc Gets the milliseconds point in the current UTC minute * @return DSecond - The milliseconds point in the current UTC minute (0..60000) */ function f_getDSecond() return UInt16 { var UInt16 v_dSecond := 0; - + // log("*** f_getDSecond: INFO: calling fx_getDSecond() ***"); v_dSecond := fx_getDSecond(); - + return v_dSecond; } - + } // End of group datetime - + group externals { - + /** * @desc Gets the current time since 01/01/1970 in UTC format * @return The current time since 01/01/1970 in UTC format */ external function fx_getCurrentTimeUtc() return UInt64; - + /** * @desc Gets the minutes of current UTC year * @return MinuteOfTheYear - minutes of current UTC year */ external function fx_getMinuteOfTheYear() return UInt16; - + /** * @desc Gets the milliseconds point in the current UTC minute * @return DSecond - the milliseconds point in the current UTC minute */ external function fx_getDSecond() return UInt16; - + /** * @desc Encode into Base64 * @return p_to_encode - The buffer to be encoded diff --git a/ttcn/LibHttp/ttcn/LibHttp_BinaryMessageBodyTypes.ttcn b/ttcn/LibHttp/ttcn/LibHttp_BinaryMessageBodyTypes.ttcn index 76a8b86..a8dd96a 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_BinaryMessageBodyTypes.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_BinaryMessageBodyTypes.ttcn @@ -22,7 +22,7 @@ module LibHttp_BinaryMessageBodyTypes { } with { variant "" } - + } with { variant "" } // End of LibHttp_BinaryMessageBodyTypes diff --git a/ttcn/LibHttp/ttcn/LibHttp_BinaryTypes.ttcn b/ttcn/LibHttp/ttcn/LibHttp_BinaryTypes.ttcn index 2606857..761a9b1 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_BinaryTypes.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_BinaryTypes.ttcn @@ -1,9 +1,9 @@ module LibHttp_BinaryTypes { // FIXME To be removed - + /** * This file is volontary empry. You have to declare all XSD files required by your project * In addition, the TTCN-3 module LibHttp_XmlMessageBodyTypes have to be updated too. */ // TODO Add here your custom binary import - + } // End of module LibHttp_BinaryTypes diff --git a/ttcn/LibHttp/ttcn/LibHttp_EncdecDeclarations.ttcn b/ttcn/LibHttp/ttcn/LibHttp_EncdecDeclarations.ttcn index e7eb077..23ea56a 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_EncdecDeclarations.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_EncdecDeclarations.ttcn @@ -1,11 +1,11 @@ module LibHttp_EncdecDeclarations { // LibHttp import from LibHttp_TypesAndValues all; - + external function fx_enc_http_message (HttpMessage p) return bitstring with {extension "prototype(convert) encode(HttpCodec)"} - + external function fx_dec_http_message (inout bitstring b, out HttpMessage p) return integer with {extension "prototype(sliding) decode(HttpCodec)"} - + } // End of module LibHttp_EncdecDeclarations diff --git a/ttcn/LibHttp/ttcn/LibHttp_Functions.ttcn b/ttcn/LibHttp/ttcn/LibHttp_Functions.ttcn index 73b9791..b329dca 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_Functions.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_Functions.ttcn @@ -1,87 +1,87 @@ module LibHttp_Functions { - + // LibCommon import from LibCommon_Time all; import from LibCommon_VerdictControl all; import from LibCommon_Sync all; - + // LibHttp import from LibHttp_TypesAndValues all; import from LibHttp_Templates all; import from LibHttp_Pics all; import from LibHttp_Pixits all; import from LibHttp_TestSystem all; - + group preambles { - + /** * @desc Setup HTTP pprotocol port */ function f_cf_01_http_up() runs on HttpComponent { - + // Map ports map(self:httpPort, system:httpPort); - + // Connect f_connect4SelfOrClientSync(); - + activate(a_cf_01_http_down()); activate(a_default_requests()); activate(a_default_responses()); - + } // End of function f_cf_01_http_up - + /** * @desc Setup HTTP pprotocol port */ function f_cf_01_http_notif_up() runs on HttpComponent { - + // Map ports map(self:httpPort, system:httpPort); map(self:httpPort_notif, system:httpPort_notif); - + // Connect f_connect4SelfOrClientSync(); - + activate(a_cf_01_http_notif_down()); activate(a_default_requests()); activate(a_default_responses()); - + } // End of function f_cf_01_http_notif_up - + } // End of group preambles - + group postambles { - + /** * @desc Shutdown HTTP pprotocol port */ function f_cf_01_http_down() runs on HttpComponent { - + // Unmap ports unmap(self:httpPort, system:httpPort); - + // Disconnect ports f_disconnect4SelfOrClientSync(); - + deactivate; } // End of function f_cf_01_http_down - + /** * @desc Shutdown HTTP pprotocol port */ function f_cf_01_http_notif_down() runs on HttpComponent { - + // Unmap ports unmap(self:httpPort, system:httpPort); unmap(self:httpPort_notif, system:httpPort_notif); - + // Disconnect ports f_disconnect4SelfOrClientSync(); - + deactivate; } // End of function f_cf_01_http_notif_down - + /** * @desc Default handling cf01 de-initialisation. */ @@ -92,7 +92,7 @@ module LibHttp_Functions { stop; } } // End of altstep a_cf_01_http_down - + /** * @desc Default handling cf01 de-initialisation. */ @@ -103,18 +103,18 @@ module LibHttp_Functions { stop; } } // End of altstep a_cf_01_http_notif_down - + } // End of group postambles - + group http_headers { - + function f_init_default_headers_list( in charstring p_header_content_type := PICS_HEADER_CONTENT_TYPE, in charstring p_header_content_text := "", out Headers p_headers ) { var integer v_i := 0; - + p_headers[v_i] := { c_header_host, { PICS_HEADER_HOST } }; v_i := v_i + 1; p_headers[v_i] := { c_header_content_type, { p_header_content_type } }; @@ -140,7 +140,7 @@ module LibHttp_Functions { f_set_headers_list(PX_ADDITIONAL_HTTP_HEADERS_KEYS, PX_ADDITIONAL_HTTP_HEADERS_VALUES, p_headers); } } // End of function f_init_default_headers_list - + function f_set_headers_list( in charstring_list p_headers_to_set, in charstring_list p_headers_value, @@ -152,7 +152,7 @@ module LibHttp_Functions { } else if (lengthof(p_headers) == 0) { return; } - + for (var integer v_idx := 0; v_idx < lengthof(p_headers_to_set); v_idx := v_idx + 1) { var integer v_jdx; for (v_jdx := 0; v_jdx < lengthof(p_headers); v_jdx := v_jdx + 1) { @@ -167,7 +167,7 @@ module LibHttp_Functions { } } // End of 'for' statement } // End of function f_set_headers_list - + function f_remove_headers_list( in charstring_list p_headers_to_remove, inout Headers p_headers @@ -178,7 +178,7 @@ module LibHttp_Functions { } else if (lengthof(p_headers) == 0) { return; } - + for (var integer v_idx := 0; v_idx < lengthof(p_headers_to_remove); v_idx := v_idx + 1) { for (var integer v_jdx := 0; v_jdx < lengthof(p_headers); v_jdx := v_jdx + 1) { if (p_headers[v_jdx].header_name == p_headers_to_remove[v_idx]) { @@ -188,7 +188,7 @@ module LibHttp_Functions { } // End of 'for' statement } // End of 'for' statement } // End of function f_remove_headers_list - + function f_get_header( in Headers p_headers, in charstring p_header_name := c_header_content_text, @@ -200,7 +200,7 @@ module LibHttp_Functions { } else if (lengthof(p_headers) == 0) { return; } - + for (var integer v_jdx := 0; v_jdx < lengthof(p_headers); v_jdx := v_jdx + 1) { if (p_headers[v_jdx].header_name == p_header_name) { p_header_value := p_headers[v_jdx].header_value; // NOTE Codec won't encode it @@ -208,7 +208,7 @@ module LibHttp_Functions { } } // End of 'for' statement } // End of function f_get_header - + /** * @desc Check HTTP response headers * @param p_headers The HTTP headers @@ -222,7 +222,7 @@ module LibHttp_Functions { ) return boolean { // Local variables var boolean v_header_matched := false; - + for (var integer v_idx := 0; v_idx < lengthof(p_headers); v_idx := v_idx + 1) { if (p_headers[v_idx].header_name == p_header_name) { if (match(p_headers[v_idx].header_value[0], p_value) == true) { @@ -231,12 +231,12 @@ module LibHttp_Functions { break; } } // End of 'for' statement - + return v_header_matched; } // End of function f_check_headers } // End of group http_headers - + group altsteps { altstep a_default_requests() runs on HttpComponent { @@ -251,10 +251,10 @@ module LibHttp_Functions { f_selfOrClientSyncAndVerdictTestBody(c_tbDone, e_error); } } // End of altstep a_default_requests - + altstep a_default_responses() runs on HttpComponent { var HttpMessage v_response; - + [] httpPort.receive( mw_http_response( mw_http_response_ok( @@ -320,7 +320,7 @@ module LibHttp_Functions { f_selfOrClientSyncAndVerdictTestBody(c_tbDone, e_error); } } // End of altstep a_default_responses - + } // end of group altsteps - + } // End of module LibHttp_Functions diff --git a/ttcn/LibHttp/ttcn/LibHttp_JSONTypes.ttcn b/ttcn/LibHttp/ttcn/LibHttp_JSONTypes.ttcn index e4a7ec3..ad0dace 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_JSONTypes.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_JSONTypes.ttcn @@ -1,9 +1,9 @@ module LibHttp_JSONTypes { // FIXME To be removed - + /** * This file is volontary empry. You have to declare all XSD files required by your project * In addition, the TTCN-3 module LibHttp_XmlMessageBodyTypes have to be updated too. */ // TODO Add here your custom RFCs import - + } // End of module LibHttp_JSONTypes diff --git a/ttcn/LibHttp/ttcn/LibHttp_JsonMessageBodyTypes.ttcn b/ttcn/LibHttp/ttcn/LibHttp_JsonMessageBodyTypes.ttcn index ef31c51..7c6be92 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_JsonMessageBodyTypes.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_JsonMessageBodyTypes.ttcn @@ -1,18 +1,18 @@ module LibHttp_JsonMessageBodyTypes { - + /** * This file volontary contains a trivial declaration of the type JsonBody. * In accordance with your TTCN-3 module LibHttp_JSONTypes, you have to change the JsonBody typing. */ // TODO Add here your custom RFCs import - + type union JsonBody { // TODO Add here your custom variants universal charstring raw } with { variant "" } - + } with { encode "JSON"; variant "" diff --git a/ttcn/LibHttp/ttcn/LibHttp_JsonTemplates.ttcn b/ttcn/LibHttp/ttcn/LibHttp_JsonTemplates.ttcn index a7aa7f0..b390758 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_JsonTemplates.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_JsonTemplates.ttcn @@ -9,13 +9,13 @@ * All rights reserved. */ module LibHttp_JsonTemplates { - + // TODO Add here your custom RFCs import - + // LibHttp import from LibHttp_JsonMessageBodyTypes all; import from LibHttp_XMLTypes all; - + template (value) JsonBody m_json_body_raw( in template (value) charstring p_raw ) := { @@ -27,5 +27,5 @@ module LibHttp_JsonTemplates { ) := { raw := p_raw } // End of template mw_json_body_raw - + } // End of module LibHttp_JsonTemplates diff --git a/ttcn/LibHttp/ttcn/LibHttp_MessageBodyTypes.ttcn b/ttcn/LibHttp/ttcn/LibHttp_MessageBodyTypes.ttcn index ed1d549..cfba5cb 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_MessageBodyTypes.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_MessageBodyTypes.ttcn @@ -1,14 +1,14 @@ module LibHttp_MessageBodyTypes { - + // LibHttp import from LibHttp_XmlMessageBodyTypes all; import from LibHttp_JsonMessageBodyTypes all; import from LibHttp_BinaryMessageBodyTypes all; - + type charstring HtmlBody; - + type charstring TextBody; - + type union HttpMessageBody { BinaryBody binary_body, HtmlBody html_body, @@ -18,7 +18,7 @@ module LibHttp_MessageBodyTypes { } with { variant "" } // End of type HttpMessageBody - + } with { encode "HttpCodec" }// End of module LibHttp_MessageBodyTypes diff --git a/ttcn/LibHttp/ttcn/LibHttp_Pics.ttcn b/ttcn/LibHttp/ttcn/LibHttp_Pics.ttcn index c4c7b8a..9a759e1 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_Pics.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_Pics.ttcn @@ -4,33 +4,33 @@ module LibHttp_Pics { * @desc HTTP major version */ modulepar integer PICS_HTTP_VERSION_MAJOR := 1; - + /** * @desc HTTP minor version */ modulepar integer PICS_HTTP_VERSION_MINOR := 1; - + /** * @desc */ modulepar charstring PICS_HEADER_HOST := "www.lisp.com"; - + /** * @desc */ modulepar charstring PICS_HEADER_CONTENT_TYPE := "application/x-its-request"; modulepar charstring PICS_HEADER_CTL_CONTENT_TYPE := "application/x-its-ctl"; modulepar charstring PICS_HEADER_CRL_CONTENT_TYPE := "application/x-its-crl"; - + /** * @desc Set to false in TOKEN header shall not be used */ modulepar boolean PICS_USE_TOKEN_HEADER := true; - + /** * @desc HTTP TOKEN value * "YWxhZGRpbjpvcGVuc2VzYW1l==" is the base64 encoding of the login:password "aladdin:opensesame" */ modulepar charstring PICS_TOKEN_HEADER := "Basic " & "YWxhZGRpbjpvcGVuc2VzYW1l==" ; // aladdin:opensesame - + } // End of module LibHttp_Pics diff --git a/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn b/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn index 9a9d42a..452e56d 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn @@ -10,44 +10,44 @@ * @see ETSI TS 103 478 */ module LibHttp_Templates { - + // LibHttp import from LibHttp_TypesAndValues all; import from LibHttp_MessageBodyTypes all; import from LibHttp_XmlMessageBodyTypes all; import from LibHttp_JsonMessageBodyTypes all; import from LibHttp_BinaryMessageBodyTypes all; - + group http_messages { - + template (value) HttpMessage m_http_request( in template (value) Request p_request ) := { request := p_request } // End of template m_http_request - + template (present) HttpMessage mw_http_request( template (present) Request p_request := ? ) := { request := p_request } // End of template mw_http_request - + template (value) HttpMessage m_http_response( in template (value) Response p_response ) := { response := p_response } // End of template m_http_response - + template (present) HttpMessage mw_http_response( template (present) Response p_response := ? ) := { response := p_response } // End of template mw_http_response - + } // End of group http_messages - + group http_headers { - + template (value) Header m_header_line( in template (value) charstring p_header_name, in template (value) charstring_list p_header_value @@ -55,11 +55,11 @@ module LibHttp_Templates { header_name := p_header_name, header_value := p_header_value } // End of template m_header_line - + } // End of group http_headers - + group http_requests { - + template (omit) Request m_http_request_get( in charstring p_uri, in template (value) Headers p_headers, @@ -72,7 +72,7 @@ module LibHttp_Templates { header := p_headers, body := p_body } // End of template m_http_request_get - + template Request mw_http_request_get( template (present) charstring p_uri := ?, template (present) Headers p_headers := ?, @@ -85,7 +85,7 @@ module LibHttp_Templates { header := p_headers, body := p_body } // End of template mw_http_request_get - + template (omit) Request m_http_request_post( in charstring p_uri, in template (value) Headers p_headers, @@ -93,7 +93,7 @@ module LibHttp_Templates { ) modifies m_http_request_get := { method := "POST" } // End of template m_http_request_post - + template Request mw_http_request_post( template (present) charstring p_uri := ?, template (present) Headers p_headers := ?, @@ -101,7 +101,7 @@ module LibHttp_Templates { ) modifies mw_http_request_get := { method := "POST" } // End of template mw_http_request_post - + template (omit) Request m_http_request_patch( in charstring p_uri, in template (value) Headers p_headers, @@ -109,7 +109,7 @@ module LibHttp_Templates { ) modifies m_http_request_get := { method := "PATCH" } // End of template m_http_request_patch - + template Request mw_http_request_patch( template (present) charstring p_uri := ?, template (present) Headers p_headers := ?, @@ -117,7 +117,7 @@ module LibHttp_Templates { ) modifies mw_http_request_get := { method := "PATCH" } // End of template mw_http_request_patch - + template (omit) Request m_http_request_put( in charstring p_uri, in template (value) Headers p_headers, @@ -125,7 +125,7 @@ module LibHttp_Templates { ) modifies m_http_request_get := { method := "PUT" } // End of template m_http_request_put - + template Request mw_http_request_put( template (present) charstring p_uri := ?, template (present) Headers p_headers := ?, @@ -133,7 +133,7 @@ module LibHttp_Templates { ) modifies mw_http_request_get := { method := "PUT" } // End of template mw_http_request_put - + template (omit) Request m_http_request_delete( in charstring p_uri, in template (value) Headers p_headers, @@ -141,7 +141,7 @@ module LibHttp_Templates { ) modifies m_http_request_get := { method := "DELETE" } // End of template m_http_request_delete - + template Request mw_http_request_delete( template (present) charstring p_uri := ?, template (present) Headers p_headers := ?, @@ -149,11 +149,11 @@ module LibHttp_Templates { ) modifies mw_http_request_get := { method := "DELETE" } // End of template mw_http_request_post - + } // End of group http_requests - + group http_responses { - + template (value) Response m_http_response_ok( in template (value) HttpMessageBody p_body, in template (value) Headers p_header @@ -167,7 +167,7 @@ module LibHttp_Templates { tls := omit, mutual_tls := omit } // End of template m_http_response_ok - + template (value) Response m_http_response_ok_no_body( in template (value) Headers p_header ) := { @@ -180,7 +180,7 @@ module LibHttp_Templates { tls := omit, mutual_tls := omit } // End of template m_http_response_ok_no_body - + template (present) Response mw_http_response_ok_no_body( template (present) Headers p_header := ? ) := { @@ -193,14 +193,14 @@ module LibHttp_Templates { tls := *, mutual_tls := * } // End of template mw_http_response_ok_no_body - + template (value) Response m_http_response_204_no_content( in template (value) Headers p_header ) modifies m_http_response_ok_no_body := { statuscode := 204, statustext := "No Content" } // End of template m_http_response_204_no_content - + template (present) Response mw_http_response_ok( template (present) HttpMessageBody p_body := ?, template (present) Headers p_header := ? @@ -214,7 +214,7 @@ module LibHttp_Templates { tls := *, mutual_tls := * } // End of template mw_http_response_ok - + template (present) Response mw_http_response_201_created( template (present) HttpMessageBody p_body := ?, template (present) Headers p_header := ? @@ -222,7 +222,7 @@ module LibHttp_Templates { statuscode := 201, statustext := "Created" } // End of template mw_http_response_201_created - + template (present) Response mw_http_response_201_created_no_status_text( template (present) HttpMessageBody p_body := ?, template (present) Headers p_header := ? @@ -230,7 +230,7 @@ module LibHttp_Templates { statuscode := 201, statustext := ? } // End of template mw_http_response_201_created_no_status_text - + template (present) Response mw_http_response_202_accepted( template (present) HttpMessageBody p_body := ?, template (present) Headers p_header := ? @@ -238,14 +238,14 @@ module LibHttp_Templates { statuscode := 202, statustext := "Accepted" } // End of template mw_http_response_202_accepted - + template (present) Response mw_http_response_204_no_content( template (present) Headers p_header := ? ) modifies mw_http_response_ok_no_body := { statuscode := 204, statustext := "No Content" } // End of template mw_http_response_204_no_content - + template (value) Response m_http_response_ko( in template (value) HttpMessageBody p_body, in template (value) Headers p_header, @@ -261,7 +261,7 @@ module LibHttp_Templates { tls := omit, mutual_tls := omit } // End of template m_http_response_ko - + template (value) Response m_http_response_ko_no_body( in template (value) Headers p_header, in template (value) integer p_statuscode := 404, @@ -276,14 +276,14 @@ module LibHttp_Templates { tls := omit, mutual_tls := omit } // End of template m_http_response_ko_no_body - + template (value) Response m_http_response_500_internal_error( in template (value) Headers p_header, in template (value) integer p_statuscode := 500, in template (value) charstring p_statustext := "Internal Error" ) modifies m_http_response_ko_no_body := { } // End of template m_http_response_ko - + template (present) Response mw_http_response_ko_no_body( template (present) Headers p_header := ?, template (present) integer p_statuscode := 404, @@ -298,7 +298,7 @@ module LibHttp_Templates { tls := omit, mutual_tls := omit } // End of template mw_http_response_ko_no_body - + template Response mw_http_response_ko( template HttpMessageBody p_body := *, template (present) Headers p_header := ? @@ -312,7 +312,7 @@ module LibHttp_Templates { tls := omit, mutual_tls := omit } // End of template mw_http_response_ko - + template (value) Response m_http_response_400_bad_request( in template (value) HttpMessageBody p_body, in template (value) Headers p_header, @@ -320,7 +320,7 @@ module LibHttp_Templates { in template (value) charstring p_statustext := "Bad Request" ) modifies m_http_response_ko := { } // End of template m_http_response_400_bad_request - + template Response mw_http_response_400_bad_request( template HttpMessageBody p_body := *, template (present) Headers p_header := ? @@ -328,7 +328,7 @@ module LibHttp_Templates { statuscode := 400, statustext := "Bad Request" } // End of template mw_http_response_400_bad_request - + template Response mw_http_response_401_unauthorized( template HttpMessageBody p_body := *, template (present) Headers p_header := ? @@ -336,7 +336,7 @@ module LibHttp_Templates { statuscode := 401, statustext := "Unauthorized" } // End of template mw_http_response_401_unauthorized - + template Response mw_http_response_403_forbidden( template HttpMessageBody p_body := *, template (present) Headers p_header := ? @@ -344,7 +344,7 @@ module LibHttp_Templates { statuscode := 403, statustext := "Forbidden" } // End of template mw_http_response_403_forbidden - + template Response mw_http_response_404_not_found( template HttpMessageBody p_body := *, template (present) Headers p_header := ? @@ -352,7 +352,7 @@ module LibHttp_Templates { statuscode := 404, statustext := "Not Found" } // End of template mw_http_response_404_not_found - + template Response mw_http_response_405_not_applicable( template HttpMessageBody p_body := *, template (present) Headers p_header := ? @@ -360,7 +360,7 @@ module LibHttp_Templates { statuscode := 405, statustext := "Not Applicable" } // End of template mw_http_response_405_not_applicable - + template Response mw_http_response_412_precondition_failed( template HttpMessageBody p_body := *, template (present) Headers p_header := ? @@ -368,71 +368,71 @@ module LibHttp_Templates { statuscode := 412, statustext := "Precondition Failed" } // End of template mw_http_response_412_not_found - + } // End of group http_responses - + group http_html_body { - + template (value) HttpMessageBody m_http_message_body_html( in template (value) HtmlBody p_html_body ) := { html_body := p_html_body } // End of template m_http_message_body_html - + template (present) HttpMessageBody mw_http_message_body_html( template (present) HtmlBody p_html_body := ? ) := { html_body := p_html_body } // End of template mw_http_message_body_html - + } // End of group http_html_body - + group http_xml_body { - + template (value) HttpMessageBody m_http_message_body_xml( in template (value) XmlBody p_xml_body ) := { xml_body := p_xml_body } // End of template m_http_message_body_xml - + template (present) HttpMessageBody mw_http_message_body_xml( template (present) XmlBody p_xml_body := ? ) := { xml_body := p_xml_body } // End of template mw_http_message_body_xml - + } // End of group http_xml_body - + group http_json_body { - + template (value) HttpMessageBody m_http_message_body_json( in template (value) JsonBody p_json_body ) := { json_body := p_json_body } // End of template m_http_message_body_json - + template (present) HttpMessageBody mw_http_message_body_json( template (present) JsonBody p_json_body := ? ) := { json_body := p_json_body } // End of template mw_http_message_body_json - + } // End of group http_json_body - + group http_binary_body { - + template (value) HttpMessageBody m_http_message_body_binary( in template (value) BinaryBody p_binary_body ) := { binary_body := p_binary_body } // End of template m_http_message_body_binary - + template (present) HttpMessageBody mw_http_message_body_binary( template (present) BinaryBody p_binary_body := ? ) := { binary_body := p_binary_body } // End of template mw_http_message_body_binary - + } // End of group http_binary_body - + } // End of module LibHttp_Templates diff --git a/ttcn/LibHttp/ttcn/LibHttp_TestSystem.ttcn b/ttcn/LibHttp/ttcn/LibHttp_TestSystem.ttcn index 9d0271c..945a87e 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_TestSystem.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_TestSystem.ttcn @@ -10,18 +10,18 @@ * @see ETSI TS 103 478 */ module LibHttp_TestSystem { - + // LibCommon import from LibCommon_Sync all; import from LibCommon_Time all; - + // LibHttp import from LibHttp_TypesAndValues all; - + type port HttpPort message { inout HttpMessage; } - + type component HttpComponent extends SelfSyncComp { port HttpPort httpPort; port HttpPort httpPort_notif; @@ -30,10 +30,10 @@ module LibHttp_TestSystem { timer tc_ac := PX_TAC; timer tc_noac := PX_TNOAC; } // End of component HttpComponent - + type component HttpTestAdapter { port HttpPort httpPort; port HttpPort httpPort_notif; } // End of component HttpTestAdapter - + } // End of module LibHttp_TestSystem diff --git a/ttcn/LibHttp/ttcn/LibHttp_TypesAndValues.ttcn b/ttcn/LibHttp/ttcn/LibHttp_TypesAndValues.ttcn index 77ca51b..0d37019 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_TypesAndValues.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_TypesAndValues.ttcn @@ -10,11 +10,11 @@ * @see ETSI TS 103 478 */ module LibHttp_TypesAndValues { - + // LibHttp import from LibHttp_MessageBodyTypes all; import from LibHttp_Pics all; - + const charstring c_header_host := "Host"; const charstring c_header_content_type := "Content-Type"; const charstring c_header_content_text := "Content-Text"; @@ -24,10 +24,10 @@ module LibHttp_TypesAndValues { const charstring c_header_pragma := "Pragma"; const charstring c_header_cache_control := "Cache-Control"; const charstring c_header_authorization := "Authorization"; - + const integer c_http_version_major := PICS_HTTP_VERSION_MAJOR; const integer c_http_version_minor := PICS_HTTP_VERSION_MINOR; - + type record of charstring charstring_list; type record Header { charstring header_name, @@ -35,9 +35,9 @@ module LibHttp_TypesAndValues { } with { variant "FIELDORDER(msb)" } - + type record of Header Headers; - + type record Request { charstring method, charstring uri, @@ -48,7 +48,7 @@ module LibHttp_TypesAndValues { } with { variant "FIELDORDER(msb)" } - + type record Response { integer version_major, integer version_minor, @@ -61,14 +61,14 @@ module LibHttp_TypesAndValues { } with { variant "FIELDORDER(msb)" } - + type union HttpMessage { Response response, Request request } with { variant "" } - + } with { variant "" encode "HttpCodec" diff --git a/ttcn/LibHttp/ttcn/LibHttp_XMLTypes.ttcn b/ttcn/LibHttp/ttcn/LibHttp_XMLTypes.ttcn index bdb9f77..a6c7f96 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_XMLTypes.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_XMLTypes.ttcn @@ -1,11 +1,11 @@ module LibHttp_XMLTypes { // FIXME To be removed - + /** * This file is volontary empry. You have to declare all XSD files required by your project * In addition, the TTCN-3 module LibHttp_XmlMessageBodyTypes have to be updated too. */ // TODO Add here your custom RFCs import - + //import from XSD all; - + } // End of module LibHttp_XMLTypes diff --git a/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn b/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn index 96cfb2f..b57854c 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_XmlMessageBodyTypes.ttcn @@ -1,23 +1,23 @@ module LibHttp_XmlMessageBodyTypes { - + /** * This file volontary contains a trivial declaration of the type XmlBody. * In accordance with your TTCN-3 module LibHttp_XMLTypes, you have to change the XmlBody typing. */ // TODO Add here your custom RFCs import - + type union XmlBodyMsg { // TODO Add here your custom variants charstring raw } with { variant "" } - + type record XmlBody { XmlBodyMsg msg, charstring raw optional } - + } with { encode "XML"; variant "" diff --git a/ttcn/LibHttp/ttcn/LibHttp_XmlTemplates.ttcn b/ttcn/LibHttp/ttcn/LibHttp_XmlTemplates.ttcn index 343300c..1c28c26 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_XmlTemplates.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_XmlTemplates.ttcn @@ -9,15 +9,15 @@ * All rights reserved. */ module LibHttp_XmlTemplates { - + // import from XSD all; - + // TODO Add here your custom RFCs import - + // LibHttp import from LibHttp_XmlMessageBodyTypes all; import from LibHttp_XMLTypes all; - + template (value) XmlBody m_xml_body_raw( in template (value) charstring p_raw ) := { @@ -31,5 +31,5 @@ module LibHttp_XmlTemplates { msg := { raw := p_raw }, raw := p_raw } // End of template mw_xml_body_raw - + } // End of module LibHttp_XmlTemplates diff --git a/ttcn/LibJson/ttcn/Json.ttcn b/ttcn/LibJson/ttcn/Json.ttcn index ff45ceb..cb7a8f5 100644 --- a/ttcn/LibJson/ttcn/Json.ttcn +++ b/ttcn/LibJson/ttcn/Json.ttcn @@ -1,5 +1,5 @@ module Json { - + // These constants are used in the Json date/time type definitions const charstring dash := "-", @@ -156,13 +156,13 @@ module Json { } with { variant "asValue" }*/ - + //Json literals //When only the true and false literals are allowed type boolean Bool; /*with { variant "Json:literal" }*/ //When only the null literal is allowed type enumerated Null { null_ }; /*with { variant "Json:literal" }*/ - + } with { encode "Json" } // End of module Json diff --git a/ttcn/LibXsd/ttcn/http_www_w3_org_XML_1998_namespace.ttcn b/ttcn/LibXsd/ttcn/http_www_w3_org_XML_1998_namespace.ttcn index dd35e71..e595c61 100644 --- a/ttcn/LibXsd/ttcn/http_www_w3_org_XML_1998_namespace.ttcn +++ b/ttcn/LibXsd/ttcn/http_www_w3_org_XML_1998_namespace.ttcn @@ -64,7 +64,7 @@ import from XSD all; is a language code for the natural language of the content of any element; its value is inherited. This name is reserved by virtue of its definition in the XML specification. - + space (as an attribute name): denotes an attribute whose value is a keyword indicating what whitespace processing discipline is intended for the content of the element; its @@ -100,7 +100,7 @@ import from XSD all; . . . - + will define a type which will schema-validate an instance element with any of those attributes */ -- GitLab From d2fa28595526041b73cd876a6130bfba4ad9e5af Mon Sep 17 00:00:00 2001 From: garciay Date: Wed, 15 May 2024 07:27:50 +0000 Subject: [PATCH 36/37] Add new template for 201 Created HTTP response --- ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn b/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn index 452e56d..c112f19 100644 --- a/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn +++ b/ttcn/LibHttp/ttcn/LibHttp_Templates.ttcn @@ -223,12 +223,19 @@ module LibHttp_Templates { statustext := "Created" } // End of template mw_http_response_201_created + template (present) Response mw_http_response_201_created_no_body( + template (present) Headers p_header := ? + ) modifies mw_http_response_ok_no_body := { + statuscode := 201, + statustext := "Created" + } // End of template mw_http_response_201_created_no_status_text + template (present) Response mw_http_response_201_created_no_status_text( template (present) HttpMessageBody p_body := ?, template (present) Headers p_header := ? ) modifies mw_http_response_ok := { statuscode := 201, - statustext := ? + statustext := "Created" } // End of template mw_http_response_201_created_no_status_text template (present) Response mw_http_response_202_accepted( -- GitLab From c579f7c7175b34426e8392e1edd3885c4b9cd185 Mon Sep 17 00:00:00 2001 From: garciay Date: Wed, 15 May 2024 09:18:33 +0000 Subject: [PATCH 37/37] Add fragmentated message support for HTTP request decoding --- ccsrc/Protocols/Http/http_codec.cc | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/ccsrc/Protocols/Http/http_codec.cc b/ccsrc/Protocols/Http/http_codec.cc index c0fac4c..bd13632 100644 --- a/ccsrc/Protocols/Http/http_codec.cc +++ b/ccsrc/Protocols/Http/http_codec.cc @@ -117,7 +117,7 @@ int http_codec::decode(const OCTETSTRING &data, LibHttp__TypesAndValues::HttpMes loggers::get_instance().log("http_codec::decode: decoding_buffer.get_len()=%d", decoding_buffer.get_len()); if (_dc.length > decoding_buffer.get_len()) { // HTTP response is fragmented // Need to bufferize the first packet and wait for the other fragments tp be received - loggers::get_instance().warning("http_codec::decode: Need to bufferize the first packet and wait for the other fragments tp be received"); + loggers::get_instance().warning("http_codec::decode: Need to bufferize the first packet and wait for the other fragments to be received"); // Set counters loggers::get_instance().log("http_codec::decode: Set bufferization counters"); _initial_content_length = _dc.length; @@ -177,7 +177,30 @@ int http_codec::decode(const OCTETSTRING &data, LibHttp__TypesAndValues::HttpMes LibHttp__TypesAndValues::Headers headers; std::string content_type; decode_headers(decoding_buffer, headers, content_type); + loggers::get_instance().log("http_codec::decode (request): _dc.length=%d", _dc.length); + loggers::get_instance().log("http_codec::decode (request): decoding_buffer.get_len()=%d", decoding_buffer.get_len()); + if (_dc.length > decoding_buffer.get_len()) { // HTTP response is fragmented + // Need to bufferize the first packet and wait for the other fragments tp be received + loggers::get_instance().warning("http_codec::decode (request): Need to bufferize the first packet and wait for the other fragments to be received"); + // Set counters + loggers::get_instance().log("http_codec::decode (request): Set bufferization counters"); + _initial_content_length = _dc.length; + _current_content_length = 0; + _bufferized_buffers.push_back(data); + _current_content_length += data.lengthof(); + loggers::get_instance().log("http_codec::decode (request): _bufferized_buffers size: %d - _current_content_length: %d", _bufferized_buffers.size(), _current_content_length); + return -2; + } else { + // Force reset counters + loggers::get_instance().log("http_codec::decode (request): Force reset bufferization counters"); + _initial_content_length = 0; + _current_content_length = 0; + } + request.header() = headers; + loggers::get_instance().log_to_hexa("Before decoding Body (request): ", decoding_buffer); + loggers::get_instance().log("http_codec::decode (request): _initial_content_length = %d", _initial_content_length); + loggers::get_instance().log("http_codec::decode (request): headers().content_length (_dc.length) = %d - decoding_buffer.get_len() = %d", _dc.length, decoding_buffer.get_len()); OPTIONAL body; body.set_to_omit(); if (decode_body(decoding_buffer, body, content_type) == -1) { @@ -459,11 +482,11 @@ int http_codec::decode_header(CHARSTRING &header_line, LibHttp__TypesAndValues:: } // End of 'for' statement header.header__value() = OPTIONAL(v); - if (m[1].str().compare("Content-Length") == 0) { + if ((m[1].str().compare("Content-Length") == 0) || (m[1].str().compare("content-length")) == 0) { // Save the the body length loggers::get_instance().log("http_codec::decode_header: decoded Content-Length %s", m[2].str().c_str()); _dc.length = std::stoi(m[2].str()); - } else if (m[1].str().compare("Transfer-Encoding") == 0) { + } else if ((m[1].str().compare("Transfer-Encoding") == 0) || (m[1].str().compare("transfer-encoding"))) { if (m[2].str().find("chunked") != std::string::npos) { _dc.chunked = true; loggers::get_instance().log("http_codec::decode_header: decoded Transfer-Encoding %x", _dc.chunked); -- GitLab