%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2005-2011. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
%%
%% %CopyrightEnd%
%%
%%

-module(csiv2_SUITE).

-include_lib("test_server/include/test_server.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("orber/COSS/CosNaming/CosNaming.hrl").
-include_lib("orber/src/orber_iiop.hrl").
-include_lib("orber/src/ifr_objects.hrl").
-include("idl_output/orber_test_server.hrl").
-include_lib("orber/COSS/CosNaming/CosNaming_NamingContextExt.hrl").
-include_lib("orber/COSS/CosNaming/CosNaming_NamingContext.hrl").
%%-include_lib("orber/src/OrberCSIv2.hrl").

-define(default_timeout, ?t:minutes(5)).

-define(match(ExpectedRes,Expr),
	fun() ->
	       AcTuAlReS = (catch (Expr)),
	       case AcTuAlReS of
		   ExpectedRes ->
		       io:format("------ CORRECT RESULT ------~n~p~n",
				 [AcTuAlReS]),
		       AcTuAlReS;
		   _ ->
		       io:format("###### ERROR ERROR ######~nRESULT:  ~p~n",
				 [AcTuAlReS]),
		       ?line exit(AcTuAlReS)
	       end
       end()).

-define(REQUEST_ID, 0).

-define(REPLY_FRAG_1, <<71,73,79,80,1,2,2,1,0,0,0,41,0,0,0,?REQUEST_ID,0,0,0,0,0,0,0,1,78,69,79,0,0,0,0,2,0,10,0,0,0,0,0,0,0,0,0,18,0,0,0,0,0,0,0,4,49>>).
%% The fragments are identical for requests and replies.
-define(FRAG_2, <<71,73,79,80,1,2,2,7,0,0,0,5,0,0,0,?REQUEST_ID,50>>).
-define(FRAG_3, <<71,73,79,80,1,2,2,7,0,0,0,5,0,0,0,?REQUEST_ID,51>>).
-define(FRAG_4, <<71,73,79,80,1,2,0,7,0,0,0,5,0,0,0,?REQUEST_ID,0>>).

%% Should X509 DER generated by, for example, OpenSSL
-define(X509DER,
	<<42>>).

%% Should X509 PEM generated by, for example, OpenSSL
-define(X509PEM,
	<<42>>).

%% IOR exported by VB (CSIv2 activated).
-define(VB_IOR,
	#'IOP_IOR'
	{type_id = "IDL:omg.org/CosNotifyComm/SequencePushConsumer:1.0",
	 profiles =
	 [#'IOP_TaggedProfile'
	  {tag = ?TAG_INTERNET_IOP,
	   profile_data = 
	   #'IIOP_ProfileBody_1_1'{
	     iiop_version = #'IIOP_Version'{major = 1,
					    minor = 2},
	     host =  "127.0.0.1",
	     port = 0,
	     object_key = [0,86,66,1,0,0,0,24,47,70,77,65,95,67,73,82,80,77,65,78,95,80,79,65,95,83,69,67,85,82,69,0,0,0,0,4,0,0,4,186,0,0,2,10,81,218,65,185],
	     components = 
	     [#'IOP_TaggedComponent'{tag = ?TAG_SSL_SEC_TRANS,
				     component_data = #'SSLIOP_SSL'{
				       target_supports = 102,
				       target_requires = 66,
				       port = 49934}},
	      #'IOP_TaggedComponent'{tag = ?TAG_CSI_SEC_MECH_LIST,
				     component_data = 
	      #'CSIIOP_CompoundSecMechList'{stateful = true,
					    mechanism_list = 
					    [#'CSIIOP_CompoundSecMech'
					     {target_requires = 66,
					      transport_mech = #'IOP_TaggedComponent'{
						tag = ?TAG_TLS_SEC_TRANS,
						component_data = 
						#'CSIIOP_TLS_SEC_TRANS'{
						  target_supports = 102,
						  target_requires = 66,
						  addresses = 
						  [#'CSIIOP_TransportAddress'
						   {host_name = "127.0.0.1",
						    port = 49934}]}},
					      as_context_mech = 
					      #'CSIIOP_AS_ContextSec'{
						target_supports = 0,
						target_requires = 0,
						client_authentication_mech = [],
						target_name = []},
					      sas_context_mech = 
					      #'CSIIOP_SAS_ContextSec'{
						target_supports = 1024,
						target_requires = 0,
						privilege_authorities = 
						[#'CSIIOP_ServiceConfiguration'
						 {syntax = 1447174401,
						  name = "Borland"}],
						supported_naming_mechanisms = [[6,
										6,
										103,
										129,
										2,
										1,
										1,
										1]],
						supported_identity_types = 15}}]}},
	      #'IOP_TaggedComponent'
	      {tag = ?TAG_CODE_SETS,
	       component_data = 
	       #'CONV_FRAME_CodeSetComponentInfo'{'ForCharData' =
						  #'CONV_FRAME_CodeSetComponent'{
						    native_code_set = 65537,
						    conversion_code_sets = [83951617]},
						  'ForWcharData' =
						  #'CONV_FRAME_CodeSetComponent'{
						   native_code_set = 65801,
						    conversion_code_sets = []}}},
	      #'IOP_TaggedComponent'{tag = ?TAG_ORB_TYPE,
				     component_data = 1447645952},
	      #'IOP_TaggedComponent'{tag = 1447645955,
				     component_data = [0,5,7,1,127]}]}}]}).

%% Common basic types
-define(OID, {2,23,130,1,1,1}).

-define(OCTET_STR, [1,2,3,4]).

-define(BIT_STR, [0,1,0,1,1]).

-define(BOOLEAN, false).

-define(ANY, [19,5,111,116,112,67,65]).

-ifdef(false).
%% PKIX1Explicit88
-define(AlgorithmIdentifier, 
	#'AlgorithmIdentifier'{algorithm = ?OID,
			       parameters = ?ANY}).

-define(Validity, #'Validity'{notBefore = {utcTime, "19820102070533.8"},
			      notAfter = {generalTime, "19820102070533.8"}}).

-define(SubjectPublicKeyInfo, 
	#'SubjectPublicKeyInfo'{algorithm = ?AlgorithmIdentifier, 
				subjectPublicKey = ?BIT_STR}).

-define(AttributeTypeAndValue,
	#'AttributeTypeAndValue'{type = ?OID,
				 value = <<19,11,69,114,105,99,115,115,111,110,32,65,66>>}).

-define(RelativeDistinguishedName, [?AttributeTypeAndValue]).

-define(RDNSequence, [?RelativeDistinguishedName]).

-define(Name, {rdnSequence, ?RDNSequence}).

-define(Version, v3).

-define(CertificateSerialNumber, 1).

-define(UniqueIdentifier, ?BIT_STR).

-define(Extension, #'Extension'{extnID = ?OID, 
				critical = ?BOOLEAN, 
				extnValue = ?OCTET_STR}).

-define(Extensions, [?Extension]).

-define(TBSCertificate,
	#'TBSCertificate'{version = ?Version, 
			  serialNumber = ?CertificateSerialNumber, 
			  signature = ?AlgorithmIdentifier, 
			  issuer = ?Name, 
			  validity = ?Validity, 
			  subject = ?Name, 
			  subjectPublicKeyInfo = ?SubjectPublicKeyInfo, 
			  issuerUniqueID = ?UniqueIdentifier, 
			  subjectUniqueID = ?UniqueIdentifier, 
			  extensions = ?Extensions}).

-define(Certificate, #'Certificate'{tbsCertificate = ?TBSCertificate, 
				    signatureAlgorithm = ?AlgorithmIdentifier, 
				    signature = ?BIT_STR}).

%% PKIX1Implicit88

-define(GeneralName, {registeredID, ?OID}).

-define(GeneralNames, [?GeneralName]).

%% PKIXAttributeCertificate	
-define(AttCertValidityPeriod, 
	#'AttCertValidityPeriod'{notBeforeTime = "19820102070533.8", 
				 notAfterTime = "19820102070533.8"}).


-define(Attribute, #'Attribute'{type = ?OID, 
				values = []}).

-define(Attributes, [?Attribute]).

-define(IssuerSerial, #'IssuerSerial'{issuer = ?GeneralNames, 
				      serial = ?CertificateSerialNumber, 
				      issuerUID = ?UniqueIdentifier}).

-define(DigestedObjectType, publicKey). %% Enum

-define(ObjectDigestInfo, 
	#'ObjectDigestInfo'{digestedObjectType = ?DigestedObjectType, 
			    otherObjectTypeID = ?OID, 
			    digestAlgorithm = ?AlgorithmIdentifier, 
			    objectDigest = ?BIT_STR}).

-define(V2Form, #'V2Form'{issuerName = ?GeneralNames, 
			  baseCertificateID = ?IssuerSerial, 
			  objectDigestInfo = ?ObjectDigestInfo}).

-define(AttCertVersion, v2).

-define(Holder, #'Holder'{baseCertificateID = ?IssuerSerial, 
			  entityName = ?GeneralNames, 
			  objectDigestInfo = ?ObjectDigestInfo}).

-define(AttCertIssuer, {v2Form, ?V2Form}).

-define(AttributeCertificateInfo,
	#'AttributeCertificateInfo'{version = ?AttCertVersion, 
				    holder = ?Holder, 
				    issuer = ?AttCertIssuer, 
				    signature = ?AlgorithmIdentifier, 
				    serialNumber = ?CertificateSerialNumber, 
				    attrCertValidityPeriod = ?AttCertValidityPeriod,
				    attributes = ?Attributes, 
				    issuerUniqueID = ?UniqueIdentifier, 
				    extensions = ?Extensions}).

-define(AttributeCertificate, 
	#'AttributeCertificate'{acinfo = ?AttributeCertificateInfo, 
				signatureAlgorithm = ?AlgorithmIdentifier, 
				signatureValue = ?BIT_STR}).


%% OrberCSIv2
-define(AttributeCertChain, 
	#'AttributeCertChain'{attributeCert = ?AttributeCertificate, 
			      certificateChain = ?CertificateChain}).

-define(CertificateChain, [?Certificate]).

-define(VerifyingCertChain, [?Certificate]).	

-endif.

%%-----------------------------------------------------------------
%% External exports
%%-----------------------------------------------------------------
-export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, cases/0,
	 init_per_suite/1, end_per_suite/1,
	 init_per_testcase/2, end_per_testcase/2,
%	 code_CertificateChain_api/1,
%	 code_AttributeCertChain_api/1,
%	 code_VerifyingCertChain_api/1,
%	 code_AttributeCertificate_api/1,
%	 code_Certificate_api/1,
%	 code_TBSCertificate_api/1,
%	 code_CertificateSerialNumber_api/1,
%	 code_Version_api/1,
%	 code_AlgorithmIdentifier_api/1,
%	 code_Name_api/1,
%	 code_RDNSequence_api/1,
%	 code_RelativeDistinguishedName_api/1,
%	 code_AttributeTypeAndValue_api/1,
%	 code_Attribute_api/1,
%	 code_Validity_api/1,
%	 code_SubjectPublicKeyInfo_api/1,
%	 code_UniqueIdentifier_api/1,
%	 code_Extensions_api/1,
%	 code_Extension_api/1,
%	 code_AttributeCertificateInfo_api/1,
%	 code_AttCertVersion_api/1,
%	 code_Holder_api/1,
%	 code_AttCertIssuer_api/1,
%	 code_AttCertValidityPeriod_api/1,
%	 code_V2Form_api/1,
%	 code_IssuerSerial_api/1,
%	 code_ObjectDigestInfo_api/1,
%	 code_OpenSSL509_api/1,
	 ssl_server_peercert_api/1,
	 ssl_client_peercert_api/1]).


%%-----------------------------------------------------------------
%% Internal exports
%%-----------------------------------------------------------------
-export([fake_server_ORB/5]).

%%-----------------------------------------------------------------
%% Func: all/1
%% Args: 
%% Returns: 
%%-----------------------------------------------------------------
suite() -> [{ct_hooks,[ts_install_cth]}].

all() -> 
    cases().

groups() -> 
    [].

init_per_group(_GroupName, Config) ->
    Config.

end_per_group(_GroupName, Config) ->
    Config.


%% NOTE - the fragment test cases must bu first since we explicitly set a request
%% id. Otherwise, the request-id counter would be increased and we cannot know
%% what it is.
cases() -> 
    [ssl_server_peercert_api, ssl_client_peercert_api].

%%-----------------------------------------------------------------
%% Init and cleanup functions.
%%-----------------------------------------------------------------

init_per_testcase(_Case, Config) ->
    Path = code:which(?MODULE),
    code:add_pathz(filename:join(filename:dirname(Path), "idl_output")),
    Dog=test_server:timetrap(?default_timeout),
    orber:jump_start(0),
    oe_orber_test_server:oe_register(),
    [{watchdog, Dog}|Config].


end_per_testcase(_Case, Config) ->
    oe_orber_test_server:oe_unregister(),
    orber:jump_stop(),
    Path = code:which(?MODULE),
    code:del_path(filename:join(filename:dirname(Path), "idl_output")),
    Dog = ?config(watchdog, Config),
    test_server:timetrap_cancel(Dog),
    ok.

init_per_suite(Config) ->
    case orber_test_lib:ssl_version() of
	no_ssl ->
	    {skip,"SSL is not installed!"};
	_ ->
	    Config
    end.

end_per_suite(Config) ->
    Config.

%%-----------------------------------------------------------------
%%  API tests for ORB to ORB, no security
%%-----------------------------------------------------------------


%%-----------------------------------------------------------------
%%  Encode and decode ASN.1 X509
%%-----------------------------------------------------------------

-ifdef(false).
%% OrberCSIv2
code_CertificateChain_api(doc) -> ["Code CertificateChain"];
code_CertificateChain_api(suite) -> [];
code_CertificateChain_api(_Config) ->
    {ok, Enc} =	
	?match({ok, _}, 
	       'OrberCSIv2':encode('CertificateChain', ?CertificateChain)),
    ?match({ok, [#'Certificate'{}]}, 
	   'OrberCSIv2':decode('CertificateChain', list_to_binary(Enc))),
    ok.

code_AttributeCertChain_api(doc) -> ["Code AttributeCertChain"];
code_AttributeCertChain_api(suite) -> [];
code_AttributeCertChain_api(_Config) ->
     {ok, Enc} = 
	?match({ok, _}, 
	       'OrberCSIv2':encode('AttributeCertChain', ?AttributeCertChain)),
    ?match({ok, #'AttributeCertChain'{}}, 
	   'OrberCSIv2':decode('AttributeCertChain', list_to_binary(Enc))),   
    ok.

code_VerifyingCertChain_api(doc) -> ["Code VerifyingCertChain"];
code_VerifyingCertChain_api(suite) -> [];
code_VerifyingCertChain_api(_Config) ->
     {ok, Enc} = 
	?match({ok, _}, 
	       'OrberCSIv2':encode('VerifyingCertChain', ?VerifyingCertChain)),
    ?match({ok, [#'Certificate'{}]}, 
	   'OrberCSIv2':decode('VerifyingCertChain', list_to_binary(Enc))),       
    ok.

%% PKIXAttributeCertificate
code_AttributeCertificate_api(doc) -> ["Code AttributeCertificate"];
code_AttributeCertificate_api(suite) -> [];
code_AttributeCertificate_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 
	       'OrberCSIv2':encode('AttributeCertificate', ?AttributeCertificate)),
    ?match({ok, #'AttributeCertificate'{}}, 
	   'OrberCSIv2':decode('AttributeCertificate', list_to_binary(Enc))),   
    ok.

code_AttributeCertificateInfo_api(doc) -> ["Code AttributeCertificateInfo"];
code_AttributeCertificateInfo_api(suite) -> [];
code_AttributeCertificateInfo_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 
	       'OrberCSIv2':encode('AttributeCertificateInfo', ?AttributeCertificateInfo)),
    ?match({ok, #'AttributeCertificateInfo'{}}, 
	   'OrberCSIv2':decode('AttributeCertificateInfo', list_to_binary(Enc))),   
    ok.

code_AttCertVersion_api(doc) -> ["Code AttCertVersion"];
code_AttCertVersion_api(suite) -> [];
code_AttCertVersion_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 
	       'OrberCSIv2':encode('AttCertVersion', ?AttCertVersion)),
    ?match({ok, ?AttCertVersion}, 
	   'OrberCSIv2':decode('AttCertVersion', list_to_binary(Enc))),   
    ok.

code_Holder_api(doc) -> ["Code Holder"];
code_Holder_api(suite) -> [];
code_Holder_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 
	       'OrberCSIv2':encode('Holder', ?Holder)),
    ?match({ok, #'Holder'{}}, 
	   'OrberCSIv2':decode('Holder', list_to_binary(Enc))),   
    ok.

code_AttCertIssuer_api(doc) -> ["Code AttCertIssuer"];
code_AttCertIssuer_api(suite) -> [];
code_AttCertIssuer_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 
	       'OrberCSIv2':encode('AttCertIssuer', ?AttCertIssuer)),
    ?match({ok, {v2Form, _}}, 
	   'OrberCSIv2':decode('AttCertIssuer', list_to_binary(Enc))),   
    ok.

code_AttCertValidityPeriod_api(doc) -> ["Code AttCertValidityPeriod"];
code_AttCertValidityPeriod_api(suite) -> [];
code_AttCertValidityPeriod_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 'OrberCSIv2':encode('AttCertValidityPeriod', ?AttCertValidityPeriod)),
    ?match({ok, #'AttCertValidityPeriod'{}}, 
	   'OrberCSIv2':decode('AttCertValidityPeriod', list_to_binary(Enc))),   
    ok.

code_V2Form_api(doc) -> ["Code V2Form"];
code_V2Form_api(suite) -> [];
code_V2Form_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 
	       'OrberCSIv2':encode('V2Form', ?V2Form)),
    ?match({ok, #'V2Form'{}}, 
	   'OrberCSIv2':decode('V2Form', list_to_binary(Enc))),   
    ok.

code_IssuerSerial_api(doc) -> ["Code IssuerSerial"];
code_IssuerSerial_api(suite) -> [];
code_IssuerSerial_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 
	       'OrberCSIv2':encode('IssuerSerial', ?IssuerSerial)),
    ?match({ok, #'IssuerSerial'{}}, 
	   'OrberCSIv2':decode('IssuerSerial', list_to_binary(Enc))),   
    ok.

code_ObjectDigestInfo_api(doc) -> ["Code ObjectDigestInfo"];
code_ObjectDigestInfo_api(suite) -> [];
code_ObjectDigestInfo_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 
	       'OrberCSIv2':encode('ObjectDigestInfo', ?ObjectDigestInfo)),
    ?match({ok, #'ObjectDigestInfo'{}}, 
	   'OrberCSIv2':decode('ObjectDigestInfo', list_to_binary(Enc))),   
    ok.

%% PKIX1Explicit88
code_Certificate_api(doc) -> ["Code Certificate"];
code_Certificate_api(suite) -> [];
code_Certificate_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 
	       'OrberCSIv2':encode('Certificate', ?Certificate)),
    ?match({ok, #'Certificate'{}}, 
	   'OrberCSIv2':decode('Certificate', list_to_binary(Enc))),   
    ok.

code_TBSCertificate_api(doc) -> ["Code TBSCertificate"];
code_TBSCertificate_api(suite) -> [];
code_TBSCertificate_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 
	       'OrberCSIv2':encode('TBSCertificate', ?TBSCertificate)),
    ?match({ok, #'TBSCertificate'{}}, 
	   'OrberCSIv2':decode('TBSCertificate', list_to_binary(Enc))),   
    ok.

code_CertificateSerialNumber_api(doc) -> ["Code CertificateSerialNumber"];
code_CertificateSerialNumber_api(suite) -> [];
code_CertificateSerialNumber_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 
	       'OrberCSIv2':encode('CertificateSerialNumber', ?CertificateSerialNumber)),
    ?match({ok, ?CertificateSerialNumber}, 
	   'OrberCSIv2':decode('CertificateSerialNumber', list_to_binary(Enc))),   
    ok.

code_Version_api(doc) -> ["Code Version"];
code_Version_api(suite) -> [];
code_Version_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 'OrberCSIv2':encode('Version', ?Version)),
    ?match({ok, ?Version}, 'OrberCSIv2':decode('Version', list_to_binary(Enc))),   
    ok.

code_AlgorithmIdentifier_api(doc) -> ["Code AlgorithmIdentifier"];
code_AlgorithmIdentifier_api(suite) -> [];
code_AlgorithmIdentifier_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 'OrberCSIv2':encode('AlgorithmIdentifier', ?AlgorithmIdentifier)),
    ?match({ok, #'AlgorithmIdentifier'{}}, 
	   'OrberCSIv2':decode('AlgorithmIdentifier', list_to_binary(Enc))),   
    ok.

code_Name_api(doc) -> ["Code Name"];
code_Name_api(suite) -> [];
code_Name_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 'OrberCSIv2':encode('Name', ?Name)),
    ?match({ok, {rdnSequence,_}}, 
	   'OrberCSIv2':decode('Name', list_to_binary(Enc))),   
    ok.

code_RDNSequence_api(doc) -> ["Code RDNSequence"];
code_RDNSequence_api(suite) -> [];
code_RDNSequence_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 'OrberCSIv2':encode('RDNSequence', ?RDNSequence)),
    ?match({ok, [[#'AttributeTypeAndValue'{}]]}, 
	   'OrberCSIv2':decode('RDNSequence', list_to_binary(Enc))),   
    ok.

code_RelativeDistinguishedName_api(doc) -> ["Code RelativeDistinguishedName"];
code_RelativeDistinguishedName_api(suite) -> [];
code_RelativeDistinguishedName_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 'OrberCSIv2':encode('RelativeDistinguishedName', ?RelativeDistinguishedName)),
    ?match({ok, [#'AttributeTypeAndValue'{}]}, 
	   'OrberCSIv2':decode('RelativeDistinguishedName', list_to_binary(Enc))),   
    ok.

code_AttributeTypeAndValue_api(doc) -> ["Code AttributeTypeAndValue"];
code_AttributeTypeAndValue_api(suite) -> [];
code_AttributeTypeAndValue_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 'OrberCSIv2':encode('AttributeTypeAndValue', ?AttributeTypeAndValue)),
    ?match({ok, #'AttributeTypeAndValue'{}}, 
	   'OrberCSIv2':decode('AttributeTypeAndValue', list_to_binary(Enc))),   
    ok.

code_Attribute_api(doc) -> ["Code Attribute"];
code_Attribute_api(suite) -> [];
code_Attribute_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 'OrberCSIv2':encode('Attribute', ?Attribute)),
    ?match({ok, #'Attribute'{}}, 
	   'OrberCSIv2':decode('Attribute', list_to_binary(Enc))),   
    ok.

code_Validity_api(doc) -> ["Code Validity"];
code_Validity_api(suite) -> [];
code_Validity_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 'OrberCSIv2':encode('Validity', ?Validity)),
    ?match({ok, #'Validity'{}}, 
	   'OrberCSIv2':decode('Validity', list_to_binary(Enc))),   
    ok.

code_SubjectPublicKeyInfo_api(doc) -> ["Code SubjectPublicKeyInfo"];
code_SubjectPublicKeyInfo_api(suite) -> [];
code_SubjectPublicKeyInfo_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 'OrberCSIv2':encode('SubjectPublicKeyInfo', ?SubjectPublicKeyInfo)),
    ?match({ok, #'SubjectPublicKeyInfo'{}}, 
	   'OrberCSIv2':decode('SubjectPublicKeyInfo', list_to_binary(Enc))),   
    ok.

code_UniqueIdentifier_api(doc) -> ["Code UniqueIdentifier"];
code_UniqueIdentifier_api(suite) -> [];
code_UniqueIdentifier_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 'OrberCSIv2':encode('UniqueIdentifier', ?UniqueIdentifier)),
    ?match({ok, _}, 'OrberCSIv2':decode('UniqueIdentifier', list_to_binary(Enc))),   
    ok.

code_Extensions_api(doc) -> ["Code Extensions"];
code_Extensions_api(suite) -> [];
code_Extensions_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 'OrberCSIv2':encode('Extensions', ?Extensions)),
    ?match({ok, [#'Extension'{}]}, 
	   'OrberCSIv2':decode('Extensions', list_to_binary(Enc))),   
    ok.

code_Extension_api(doc) -> ["Code Extension"];
code_Extension_api(suite) -> [];
code_Extension_api(_Config) ->
    {ok, Enc} = 
	?match({ok, _}, 'OrberCSIv2':encode('Extension', ?Extension)),
    ?match({ok, #'Extension'{}}, 
	   'OrberCSIv2':decode('Extension', list_to_binary(Enc))),   
    ok.

%% OpenSSL generated x509 Certificate
code_OpenSSL509_api(doc) -> ["Code OpenSSL generated x509 Certificate"];
code_OpenSSL509_api(suite) -> [];
code_OpenSSL509_api(_Config) ->
    {ok, Cert} = 
	?match({ok, #'Certificate'{}}, 
	       'OrberCSIv2':decode('Certificate', ?X509DER)),
    AttrCertChain = #'AttributeCertChain'{attributeCert = ?AttributeCertificate, 
					  certificateChain = [Cert]},
    {ok, EAttrCertChain} = 
	?match({ok, _}, 'OrberCSIv2':encode('AttributeCertChain', AttrCertChain)),
    ?match({ok, #'AttributeCertChain'{}}, 
	   'OrberCSIv2':decode('AttributeCertChain', list_to_binary(EAttrCertChain))),
    ok.

-endif.

%%-----------------------------------------------------------------
%%  Test ssl:peercert
%%-----------------------------------------------------------------
ssl_server_peercert_api(doc) -> ["Test ssl:peercert (server side)"];
ssl_server_peercert_api(suite) -> [];
ssl_server_peercert_api(_Config) ->
    case os:type() of
        vxworks ->
	    {skipped, "No SSL-support for VxWorks."};
        _ ->
	    Options = orber_test_lib:get_options(iiop_ssl, server, 
						 2, [{iiop_ssl_port, 0}]),
	    {ok, ServerNode, ServerHost} = 
		?match({ok,_,_}, orber_test_lib:js_node(Options)),
	    ServerPort = orber_test_lib:remote_apply(ServerNode, orber, iiop_ssl_port, []),
	    SSLOptions = orber_test_lib:get_options(ssl, client),
 	    {ok, Socket} = 
		?match({ok, _}, fake_client_ORB(ssl, ServerHost, ServerPort, SSLOptions)),
	    {ok, _PeerCert} = ?match({ok, _}, orber_socket:peercert(ssl, Socket)),
%% 	    ?match({ok, {rdnSequence, _}}, orber_socket:peercert(ssl, Socket, [pkix, subject])),
%% 	    ?match({ok, {rdnSequence, _}}, orber_socket:peercert(ssl, Socket, [ssl, subject])),
%	    ?match({ok, #'Certificate'{}}, 
%		   'OrberCSIv2':decode('Certificate', PeerCert)),
	    destroy_fake_ORB(ssl, Socket),
	    ok
    end.

ssl_client_peercert_api(doc) -> ["Test ssl:peercert (client side)"];
ssl_client_peercert_api(suite) -> [];
ssl_client_peercert_api(_Config) ->
    case os:type() of
        vxworks ->
	    {skipped, "No SSL-support for VxWorks."};
        _ ->
	    Options = orber_test_lib:get_options(iiop_ssl, client, 
						 2, [{iiop_ssl_port, 0}]),
	    {ok, ClientNode, _ClientHost} = 
		?match({ok,_,_}, orber_test_lib:js_node(Options)),
	    crypto:start(),
	    ssl:start(),
	    ssl:seed("testing"),
	    SSLOptions = orber_test_lib:get_options(ssl, server),
	    {ok, LSock} = ?match({ok, _}, ssl:listen(0, SSLOptions)),
	    {ok, {_Address, LPort}} = ?match({ok, {_, _}}, ssl:sockname(LSock)),
	    IOR = ?match({'IOP_IOR',_,_}, 
			 iop_ior:create_external({1, 2}, "IDL:FAKE:1.0", 
						 "localhost", 6004, "FAKE", 
						 [#'IOP_TaggedComponent'
						  {tag=?TAG_SSL_SEC_TRANS, 
						   component_data=#'SSLIOP_SSL'
						   {target_supports = 2, 
						    target_requires = 2, 
						    port = LPort}}])),
	    spawn(orber_test_lib, remote_apply, 
		  [ClientNode, corba_object, non_existent, [IOR]]),
	    {ok, Socket} = ?match({ok, _}, ssl:transport_accept(LSock)),
	    ?match(ok, ssl:ssl_accept(Socket)),
	    
	    {ok, _PeerCert} = ?match({ok, _}, orber_socket:peercert(ssl, Socket)),
%% 	    ?match({ok, {rdnSequence, _}}, orber_socket:peercert(ssl, Socket, [pkix, subject])),
%% 	    ?match({ok, {rdnSequence, _}}, orber_socket:peercert(ssl, Socket, [ssl, subject])),
%	    ?match({ok, #'Certificate'{}}, 
%		   'OrberCSIv2':decode('Certificate', PeerCert)),
	    ssl:close(Socket),
	    ssl:close(LSock),
	    ssl:stop(),
	    ok
    end.

%%-----------------------------------------------------------------
%% Local functions.
%%-----------------------------------------------------------------
-ifdef(false).
%% Not used yet.
context_test(Obj) ->
    IDToken1 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTAbsent, 
				    value = true},
    IDToken2 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTAnonymous, 
				    value = false},
    IDToken3 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTPrincipalName, 
				    value = [0,255]},
    IDToken4 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTX509CertChain, 
				    value = [1,255]},
    IDToken5 = #'CSI_IdentityToken'{label = ?CSI_IdentityTokenType_ITTDistinguishedName, 
				    value = [2,255]},
    IDToken6 = #'CSI_IdentityToken'{label = ?ULONGMAX, 
				    value = [3,255]},

    MTEstablishContext1 = #'CSI_SASContextBody'
      {label = ?CSI_MsgType_MTEstablishContext, 
       value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX, 
				       authorization_token = 
				       [#'CSI_AuthorizationElement'
					{the_type = ?ULONGMAX, 
					 the_element = [0,255]}], 
				       identity_token = IDToken1, 
				       client_authentication_token = [1, 255]}},
    MTEstablishContext2 = #'CSI_SASContextBody'
      {label = ?CSI_MsgType_MTEstablishContext, 
       value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX, 
				       authorization_token = 
				       [#'CSI_AuthorizationElement'
					{the_type = ?ULONGMAX, 
					 the_element = [0,255]}], 
				       identity_token = IDToken2, 
				       client_authentication_token = [1, 255]}},
    MTEstablishContext3 = #'CSI_SASContextBody'
      {label = ?CSI_MsgType_MTEstablishContext, 
       value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX, 
				       authorization_token = 
				       [#'CSI_AuthorizationElement'
					{the_type = ?ULONGMAX, 
					 the_element = [0,255]}], 
				       identity_token = IDToken3, 
				       client_authentication_token = [1, 255]}},
    MTEstablishContext4 = #'CSI_SASContextBody'
      {label = ?CSI_MsgType_MTEstablishContext, 
       value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX, 
				       authorization_token = 
				       [#'CSI_AuthorizationElement'
					{the_type = ?ULONGMAX, 
					 the_element = [0,255]}], 
				       identity_token = IDToken4, 
				       client_authentication_token = [1, 255]}},
    MTEstablishContext5 = #'CSI_SASContextBody'
      {label = ?CSI_MsgType_MTEstablishContext, 
       value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX, 
				       authorization_token = 
				       [#'CSI_AuthorizationElement'
					{the_type = ?ULONGMAX, 
					 the_element = [0,255]}], 
				       identity_token = IDToken5, 
				       client_authentication_token = [1, 255]}},
    MTEstablishContext6 = #'CSI_SASContextBody'
      {label = ?CSI_MsgType_MTEstablishContext, 
       value = #'CSI_EstablishContext'{client_context_id = ?ULONGLONGMAX, 
				       authorization_token = 
				       [#'CSI_AuthorizationElement'
					{the_type = ?ULONGMAX, 
					 the_element = [0,255]}], 
				       identity_token = IDToken6, 
				       client_authentication_token = [1, 255]}},
    MTCompleteEstablishContext = #'CSI_SASContextBody'
      {label = ?CSI_MsgType_MTCompleteEstablishContext, 
       value = #'CSI_CompleteEstablishContext'{client_context_id = ?ULONGLONGMAX, 
					       context_stateful = false,
					       final_context_token = [1, 255]}},
    MTContextError = #'CSI_SASContextBody'
      {label = ?CSI_MsgType_MTContextError, 
       value = #'CSI_ContextError'{client_context_id = ?ULONGLONGMAX,
				   major_status = 1, 
				   minor_status = 2, 
				   error_token = [2,255]}},
    MTMessageInContext = #'CSI_SASContextBody'
      {label = ?CSI_MsgType_MTMessageInContext, 
       value = #'CSI_MessageInContext'{client_context_id = ?ULONGLONGMAX, 
				       discard_context = true}},
    Ctx = [#'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService, 
				 context_data = MTEstablishContext1},
	   #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService, 
				 context_data = MTEstablishContext2},
	   #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService, 
				 context_data = MTEstablishContext3},
	   #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService, 
				 context_data = MTEstablishContext4},
	   #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService, 
				 context_data = MTEstablishContext5},
	   #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService, 
				 context_data = MTEstablishContext6},
	   #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService, 
				 context_data = MTCompleteEstablishContext},
	   #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService, 
				 context_data = MTContextError},
	   #'IOP_ServiceContext'{context_id=?IOP_SecurityAttributeService, 
				 context_data = MTMessageInContext}],
    ?line ?match(ok, orber_test_server:testing_iiop_context(Obj, [{context, Ctx}])).


fake_server_ORB(Type, Port, Options) ->
    start_ssl(Type),
    {ok, ListenSocket, NewPort} =
	orber_socket:listen(Type, Port, 
			    [{active, false}|Options]),
    Socket = orber_socket:accept(Type, ListenSocket),
    orber_socket:post_accept(Type, Socket),
    {ok, Socket, NewPort}.

-endif.

fake_server_ORB(Type, Port, Options, Action, Data) ->
    start_ssl(Type),
    {ok, ListenSocket, _NewPort} = 
	orber_socket:listen(Type, Port, [{active, false}|Options]),
    Socket = orber_socket:accept(Type, ListenSocket),
    orber_socket:post_accept(Type, Socket),
    do_server_action(Type, Socket, Action, Data),
    orber_socket:close(Type, Socket),
    ok.

start_ssl(ssl) ->
    crypto:start(),
    ssl:start(),
    ssl:seed("testing");
start_ssl(_) ->
    ok.


destroy_fake_ORB(ssl, Socket) ->
    orber_socket:close(ssl, Socket),
    ssl:stop();
destroy_fake_ORB(Type, Socket) ->
    orber_socket:close(Type, Socket).

fake_client_ORB(Type, Host, Port, Options) ->
    start_ssl(Type),
    Socket = orber_socket:connect(Type, Host, Port, [{active, false}|Options]),
    {ok, Socket}.

-ifdef(false).
%% Not used yet.

fake_client_ORB(Type, Host, Port, Options, Action, Data) ->
    start_ssl(Type),
    Socket = orber_socket:connect(Type, Host, Port, [{active, false}|Options]),
    Result = do_client_action(Type, Socket, Action, Data),
    orber_socket:close(Type, Socket),
    Result.

do_client_action(Type, Socket, fragments, FragList) ->
    ok = send_data(Type, Socket, FragList),
    {ok, Bytes} = gen_tcp:recv(Socket, 0),
    {#reply_header{request_id = ?REQUEST_ID, reply_status = no_exception}, ok, [Par]} = 
	cdr_decode:dec_message({tk_void,[tk_any],[tk_any]}, Bytes),
    Par;
do_client_action(Type, Socket, fragments_max, FragList) ->
    ok = send_data(Type, Socket, FragList),
    {ok, Bytes} = gen_tcp:recv(Socket, 0),
    {#reply_header{request_id = ?REQUEST_ID, reply_status = system_exception}, Exc, []} = 
	cdr_decode:dec_message({tk_void,[tk_any],[tk_any]}, Bytes),
    Exc;
do_client_action(Type, Socket, message_error, Data) ->
    ok = send_data(Type, Socket, Data),
    {ok,Bytes} = gen_tcp:recv(Socket, 0),
    'message_error' = cdr_decode:dec_message({tk_void,[tk_any],[tk_any]}, Bytes),
    ok;
do_client_action(_Type, _Socket, _Action, _Data) ->
    ok.

-endif.

do_server_action(Type, Socket, fragments, FragList) ->
    {ok, _B} = gen_tcp:recv(Socket, 0),
    ok = send_data(Type, Socket, FragList);
do_server_action(_Type, _Socket, _Action, _Data) ->
    ok.


send_data(_Type, _Socket, []) ->
    ok;
send_data(Type, Socket, [H|T]) ->
    orber_socket:write(Type, Socket, H),
    send_data(Type, Socket, T).
    
