LibSip_Steps.ttcn 144 KB
Newer Older
 *	@author 	STF 346, STF366, STF368, STF369, STF450
 *  @version    $Id$
 *	@desc		This module provides the types used by the test component 
 *              for SIP-IMS tests.
 *              This module is part of LibSipV2.
schmitting's avatar
schmitting committed
module LibSip_Steps //MRO
schmitting's avatar
schmitting committed
	//LibCommon 
	import from LibCommon_Sync all ;
	import from LibCommon_VerdictControl all ;
	//LibSip
	import from LibSip_SIPTypesAndValues all;
	import from LibSip_SDPTypes all;
	import from LibSip_Templates all;
	import from LibSip_Interface all;
	import from LibSip_PIXITS all;
	import from LibSip_XMLTypes all;

group externalfunctions {
	
	//Return random charstring
	external function fx_rndStr() return charstring;
	// Return the equivalent string in lower case
	external function fx_putInLowercase(charstring par_string) return charstring;
	
	external function fx_getIpAddr(charstring host_name) return charstring;

	// External function to generate a digest response.
	// References:
	//   * RFC 2617 HTTP Authentication: Basic and Digest Access
	//     Authentication, and
	//   * RFC 1321 The MD5 Message-Digest Algorithm
	// See RFC 2617, chapter 5 Sample implementation, for example usage, as
	// the signature of calculateDigestResponse is according to the example
	// given in the RFC.
	//
	external function fx_calculateDigestResponse(
	  charstring nonce,
	  charstring cnonce,
	  charstring user,
	  charstring realm,
	  charstring passwd,
	  charstring alg,
	  charstring nonceCount,
	  charstring method,
	  charstring qop,
	  charstring URI,
	  charstring HEntity) return charstring;

}

group ParameterOperations {

	/**
	 * @desc function to generate a 32 bits random number as a charstring for tag field
	 * (used as e.g.: tag in from-header field, or branch parameter in via header)
	 * @return random value with at least 32 bits of randomness
	 * 
	 */
	 function f_getRndTag() return charstring
	{
	  var charstring tag_value;
	  //tag_value is initialized with a random value with at least 32 bits of randomness
	  // 4294967296 is a 32 bits integer
	  tag_value := fx_rndStr()&fx_rndStr();
	  return(tag_value);
	}

	/**
	 * @desc  Function to prepare credentials for request that has an empty
	 * entity body such as a REGISTER message.
	 * @param p_userprofile to get important parameters
	 * @return Credentials field
	 */
garciay's avatar
garciay committed
	function f_calculatecCredentials_empty(in SipUserProfile p_userprofile, in boolean p_algorithm:=false) return Credentials
	  var template Credentials v_result;
	      
	  var charstring v_nonce := "";
	      
	  // RFC 2617 3.2.2 username:
	  // The name of user in the specified realm.
	  var charstring v_username := p_userprofile.privUsername;
	      
	  var charstring v_realm := p_userprofile.registrarDomain;
	      
	  var charstring v_uri := c_sipScheme & ":" & p_userprofile.registrarDomain;
	           
	  var charstring v_response := "";
	 
	  // Construct credentials for an Authorization field of a request.
garciay's avatar
garciay committed
	  if (not p_algorithm) {
          v_result :=
          {
            digestResponse :=
            {
              { id := "username", paramValue := v_username },
              { id := "realm", paramValue := v_realm },
              { id := "uri", paramValue := v_uri },
              { id := "nonce=""""", paramValue := omit }, // already enclosed to " characters
              { id := "response=""""", paramValue := omit } // already enclosed to " characters
          }}; 
	  } else {
          v_result :=
          {
            digestResponse :=
            {
              { id := "username", paramValue := v_username },
              { id := "realm", paramValue := v_realm },
              { id := "uri", paramValue := v_uri },
              { id := "nonce=""""", paramValue := omit }, // already enclosed to " characters
              { id := "response=""""", paramValue := omit }, // already enclosed to " characters
garciay's avatar
garciay committed
              { id := "algorithm", paramValue := PX_AUTH_ALGORITHM } // already enclosed to " characters
garciay's avatar
garciay committed
          }};
	  }
	  return valueof(v_result);
	}


	/**
	 * 
	 * @desc  Function to calculate credentials for request that has an empty
	 * entity body such as a REGISTER message.
	 * @param p_userprofile to get important parameters
	 * @param p_method (can be "REGISTER", "INVITE",....)
	 * @param p_challenge parameter from 4xx response
	 * @return Credentials field
	 * @verdict 
	 */
	function f_calculatecCredentials(in SipUserProfile p_userprofile, in charstring p_method, 
		in CommaParam_List p_challenge) return Credentials
	{
	  var template Credentials v_result;
      
	  var charstring v_nonce := "";
      
	  // Use a fixed client nonce.
	  var charstring v_cnonce := "1317265";
      
	  // RFC 2617 3.2.2 username:
	  // The name of user in the specified realm.
	  var charstring v_username := p_userprofile.privUsername;
      
	  var charstring v_realm;
      
	  // RFC 2617 3.2.2.2 passwd:
	  // A known shared secret, the password of user of the specified
	  // username.
	  var charstring v_passwd := p_userprofile.passwd;
      
	  var charstring v_algorithm;
      
	  // Use a fixed nonce count.
	  const charstring c_nonceCount := "00000002";

	  var charstring v_qop := p_userprofile.qop;
      
	  var charstring v_uri := c_sipScheme & ":" & p_userprofile.registrarDomain;
      
	  // MD5 hash of empty entity body.
	  const charstring c_hEntity := "d41d8cd98f00b204e9800998ecf8427e";
      
	  var charstring v_response;
	  var charstring v_opaque;
      
      
	  // extract nonce, realm, algorithm, and opaque from challenge
      
	  v_nonce := f_extractParamValueFromChallenge(p_challenge, "nonce"); 
	  v_realm := f_extractParamValueFromChallenge(p_challenge, "realm"); 
	  v_algorithm := f_extractParamValueFromChallenge(p_challenge, "algorithm");
	  v_opaque := f_extractParamValueFromChallenge(p_challenge, "opaque");
      
	  // calculate a digest response for the Authorize header
	  v_response := fx_calculateDigestResponse(
		v_nonce,
		v_cnonce,
		v_username,
		v_realm,
		v_passwd,
		v_algorithm,
		c_nonceCount,
		p_method,
		v_qop,
		v_uri,
		c_hEntity);
      
	  // Construct credentials for an Authorization field of a request.
	  v_result :=
	  {
		digestResponse :=
		{
		  { id := "username", paramValue := v_username },
		  { id := "realm", paramValue := v_realm },
		  { id := "nonce", paramValue := v_nonce },
		  { id := "uri", paramValue := v_uri },
		  { id := "response", paramValue := v_response },
		  { id := "algorithm="&v_algorithm, paramValue := omit }, // algorithm is not enclosed to " characters
		  { id := "cnonce", paramValue := v_cnonce },
		  { id := "opaque", paramValue := v_opaque }, // already enclosed to " characters
		  { id := "qop="&v_qop, paramValue := omit },//qop
		  { id := "nc="&c_nonceCount, paramValue := omit }//nonceCount
		}
	  };
      
     return  valueof(v_result);
	}

	/**
	 * 
	 * @desc  Function to calculate credentials for request that has an empty
	 * entity body such as a REGISTER message. NO RESPONSE value to cause an error!
	 * @param p_userprofile to get important parameters
	 * @param p_method (can be "REGISTER", "INVITE",....)
	 * @param p_challenge parameter from 4xx response
	 * @return Credentials field
	 * @verdict 
	 */
	function f_calculatecCredentials_wo_response(in SipUserProfile p_userprofile, in charstring p_method, 
		in CommaParam_List p_challenge) return Credentials
	{
	  var Credentials v_result;
      
	  var charstring v_nonce := "";
      
	  // Use a fixed client nonce.
	  var charstring v_cnonce := "1317265";
      
	  // RFC 2617 3.2.2 username:
	  // The name of user in the specified realm.
	  var charstring v_username := p_userprofile.privUsername;
      
	  var charstring v_realm;
      
	  // RFC 2617 3.2.2.2 passwd:
	  // A known shared secret, the password of user of the specified
	  // username.
	  var charstring v_passwd := p_userprofile.passwd;
      
	  var charstring v_algorithm;
      
	  // Use a fixed nonce count.
	  const charstring c_nonceCount := "00000002";

	  var charstring v_qop := p_userprofile.qop;
      
	  var charstring v_uri := c_sipScheme & ":" & p_userprofile.registrarDomain;
      
	  // MD5 hash of empty entity body.
	  const charstring c_hEntity := "d41d8cd98f00b204e9800998ecf8427e";
      
	  var charstring v_response;
	  var charstring v_opaque;
      
      
	  // extract nonce, realm, algorithm, and opaque from challenge
      
	  v_nonce := f_extractParamValueFromChallenge(p_challenge, "nonce"); 
	  v_realm := f_extractParamValueFromChallenge(p_challenge, "realm"); 
	  v_algorithm := f_extractParamValueFromChallenge(p_challenge, "algorithm");
	  v_opaque := f_extractParamValueFromChallenge(p_challenge, "opaque");
      
	  // calculate a digest response for the Authorize header
	  v_response := fx_calculateDigestResponse(
		v_nonce,
		v_cnonce,
		v_username,
		v_realm,
		v_passwd,
		v_algorithm,
		c_nonceCount,
		p_method,
		v_qop,
		v_uri,
		c_hEntity);
      
	  // Construct credentials for an Authorization field of a request.
	  v_result :=
	  {
		digestResponse :=
		{
		  { id := "username", paramValue := v_username },
		  { id := "realm", paramValue := v_realm },
		  { id := "nonce", paramValue := v_nonce },
		  { id := "uri", paramValue := v_uri },
//		  { id := "response", paramValue := v_response }, // not included to cause an error
		  { id := "algorithm="&v_algorithm, paramValue := omit }, // algorithm is not enclosed to " characters
		  { id := "cnonce", paramValue := v_cnonce },
		  { id := "opaque=""""", paramValue := omit }, // already enclosed to " characters
		  { id := "qop="&v_qop, paramValue := omit },//qop
		  { id := "nc="&c_nonceCount, paramValue := omit }//nonceCount
		}
	  };
      
	  return v_result;
	}
	
	/**
		* 
		* @desc  Function to calculate credentials for response 401 - WWW-Authorization
		* @param p_qop of the peer UE (alternatively )
		* @param p_authorization parameter from 1st REGISTER request
		* @return Credentials field
		* @verdict 
		*/
	function f_calculatecChallenge_forWWWAuthorizationBody(in charstring p_qop, in Authorization p_authorization) return Challenge
	{ 
			var CommaParam_List v_challenge;
	  
			if (ischosen(p_authorization.body[0].digestResponse))
				{v_challenge := p_authorization.body[0].digestResponse}
				else {v_challenge := p_authorization.body[0].otherResponse.authParams};
      
			return (f_calculatecChallenge_forWWWAuthorization(p_qop,v_challenge));
	}
	
	/**
	 * 
	 * @desc  Function to calculate credentials for response 401 - WWW-Authorization
	 * @param p_qop of the peer UE (alternatively )
	 * @param p_challenge parameter from 1st REGISTER request
	 * @return Credentials field
	 * @verdict 
	 */
	function f_calculatecChallenge_forWWWAuthorization(in charstring p_qop, in CommaParam_List p_challenge) return Challenge
	{
	  var Challenge v_result;

	  var charstring v_realm;
      
	  var charstring v_qop := p_qop;

	  v_realm := f_extractParamValueFromChallenge(p_challenge, "realm");
      
	  // Construct credentials for an Authorization field of a request.
	  v_result :=
	  {
		digestCln :=
		{
		  { id := "realm", paramValue := v_realm },
		  { id := "nonce", paramValue := "0edff6c521cc3f407f2d9e01cf6ed82b"},
garciay's avatar
garciay committed
		  { id := "algorithm", paramValue := PX_AUTH_ALGORITHM/*TODO To be removed c_algorithm*/ }, // algorithm is not enclosed with " characters
		  { id := "ck", paramValue := "00112233445566778899aabbccddeeff" },
		  { id := "ik", paramValue := "ffeeddccbbaa99887766554433221100" }, // already enclosed to " characters
		  { id := "qop="""&v_qop&"""", paramValue := omit }//qop

		}
	  };
      
	  return v_result;
	}
	
	/**
	* 
	* @desc  Function to calculate credentials for request that has an empty
	* entity body such as a REGISTER message and at the end put different private name
	* @param p_userprofile to get important parameters
	* @param p_method (can be "REGISTER", "INVITE",....)
	* @param p_challenge parameter from 4xx response
	* @return Credentials field
	* @verdict 
	*/
   function f_calculatecCredentialsAndChangeUserName(in SipUserProfile p_userprofile, in charstring p_method, 
	   in CommaParam_List p_challenge) return Credentials
   {
	 var Credentials v_result;
      
	 var charstring v_nonce := "";
      
	 // Use a fixed client nonce.
	 var charstring v_cnonce := "1317265";
      
	 // RFC 2617 3.2.2 username:
	 // The name of user in the specified realm.
	 var charstring v_username := p_userprofile.privUsername;
      
	 var charstring v_realm;
      
	 // RFC 2617 3.2.2.2 passwd:
	 // A known shared secret, the password of user of the specified
	 // username.
	 var charstring v_passwd := p_userprofile.passwd;
      
	 var charstring v_algorithm;
      
	 // Use a fixed nonce count.
	 const charstring c_nonceCount := "00000002";

	 var charstring v_qop := p_userprofile.qop;
      
	 var charstring v_uri := c_sipScheme & ":" & p_userprofile.registrarDomain;
      
	 // MD5 hash of empty entity body.
	 const charstring c_hEntity := "d41d8cd98f00b204e9800998ecf8427e";
      
	 var charstring v_response;
	 var charstring v_opaque;
      
      
	 // extract nonce, realm, algorithm, and opaque from challenge
      
	 v_nonce := f_extractParamValueFromChallenge(p_challenge, "nonce"); 
	 v_realm := f_extractParamValueFromChallenge(p_challenge, "realm"); 
	 v_algorithm := f_extractParamValueFromChallenge(p_challenge, "algorithm");
	 v_opaque := f_extractParamValueFromChallenge(p_challenge, "opaque");
      
	 // calculate a digest response for the Authorize header
	 v_response := fx_calculateDigestResponse(
	   v_nonce,
	   v_cnonce,
	   v_username,
	   v_realm,
	   v_passwd,
	   v_algorithm,
	   c_nonceCount,
	   p_method,
	   v_qop,
	   v_uri,
	   c_hEntity);
      
	 // Construct credentials for an Authorization field of a request.
	 v_result :=
	 {
	   digestResponse :=
	   {
		 { id := "username", paramValue := "DifferentToPrivateUser"},
		 { id := "realm", paramValue := v_realm },
		 { id := "nonce", paramValue := v_nonce },
		 { id := "uri", paramValue := v_uri },
		 { id := "response", paramValue := v_response },
		 { id := "algorithm="&v_algorithm, paramValue := omit }, // algorithm is not enclosed to " characters
		 { id := "cnonce", paramValue := v_cnonce },
		 { id := "opaque=""""", paramValue := omit }, // already enclosed to " characters
		 { id := "qop="&v_qop, paramValue := omit },//qop
		 { id := "nc="&c_nonceCount, paramValue := omit }//nonceCount
	   }
	 };
      
	 return v_result;
   }
	

   /**
	* 
	* @desc Function to check if param related to id from CommanParam_List exist
	* containing challenge.
	* @param p_challenge parameter from 4xx response
	* @param p_id name of parameter("nonce", "realm", "ck", "ik"...)
	* @return  parameter p_id value 
	*/
   function f_checkParamValueFromChallengeIfPresent(in CommaParam_List p_challenge, in charstring p_id) return boolean
   {
	 var boolean v_result := false;
	 var integer v_len := sizeof(p_challenge);
	 var charstring v_id := fx_putInLowercase(p_id);
      
	 for (var integer i := 0; i < v_len; i := i + 1)
	 {
	   if (fx_putInLowercase(p_challenge[i].id) == v_id)
	   {
		 v_result := true;
	   }
	 }
      
	 return v_result;
   }	
    
    /**
	* 
	* @desc Function to check if tag is present in SemicolonParam_List
	* @param p_param_l SemicolonParam_List
	* @return  boolean  true if tag is present 
	*/
    function f_checkTagPresent(SemicolonParam_List p_param_l) runs on SipComponent return boolean {
	    var integer v_numberOfParams;
	    var integer i := 0;

	    v_numberOfParams := sizeof (p_param_l);
	    while (i < v_numberOfParams) {
		    if (fx_putInLowercase(p_param_l[i].id) == c_tagId) {
			    return (true);
		    }
		    i := i + 1;
	    }
	    return (false);
    }

	/**
	 * @desc Function to extract paramValue related to id from CommanParam_List
	 * containing challenge.
	 * @param p_challenge parameter from 4xx response
	 * @param p_id name of parameter("nonce", "realm",...)
	 * @return  parameter p_id value 
	 */
	function f_extractParamValueFromChallenge(in CommaParam_List p_challenge, in charstring p_id) return charstring
	{
	  var charstring v_result := "";
	  var integer v_len := sizeof(p_challenge);
	  var charstring v_id := fx_putInLowercase(p_id);
      
	  for (var integer i := 0; i < v_len; i := i + 1)
	  {
		if (fx_putInLowercase(p_challenge[i].id) == v_id)
		{
		  v_result := p_challenge[i].paramValue;
		}
	  }

	  if (v_result == "")
	  {
		if(match(p_id,"algorithm")) 
		{
			v_result := "MD5"
		}
		else if(match(p_id,"opaque"))
		{
			v_result := ""
		}
		else
		{
		var charstring v_tmpchar := "Cannot acquire value from credentials.";
		log ("Cannot acquire value from credentials.");
		setverdict(inconc);
		stop;
		}
	  }
      
	  return v_result;
	}
	
}//end group ParameterOperations

group FieldOperations {

	/**
	 * 
	 * @desc function adds "Tag"-parameter in "To"-headerfield
	 * @param p_to To header field that should get a Tag parameter
	 * 
	 */
	function f_addTagInTo(inout To p_to) runs on SipComponent
	{      
	  f_addParameterTagIfNotPresent(c_tagId, f_getRndTag(), p_to); 
	}

	/**
	 * 
	 * @desc addition of a single parameter in the via header field
	 * @param p_parameter_name name of parameter to be added
	 * @param p_parameter_value value of parameter to be added
	 * @param p_viaBody the via parameter to be extended
	 * @verdict 
	 */
	function f_addParameterIfNotPresent(
		in charstring p_parameter_name,
		in charstring p_parameter_value,
		inout ViaBody p_viaBody) 
		
		{
		if (ispresent (p_viaBody.viaParams)) {
			return;
		}
		p_viaBody.viaParams := {
			{
				p_parameter_name,
				p_parameter_value
			}
		};
	}    
    
	/**
	 * 
	 * @desc function to addd a parameter to the "To" header field (if there is not any parameter)
	 * @param p_parameter_name name of the parameter to be added
	 * @param p_parameter_value value of the paramter to be added
	 * @param p_to "To" header field to be extended
	 * @verdict 
	 */
	function f_addParameterTagIfNotPresent(
		in charstring p_parameter_name,
		in charstring p_parameter_value,
		inout To p_to) 
		
		{
		if (ispresent (p_to.toParams)) {
			return;
		}
		p_to.toParams := {
			{
				p_parameter_name,
				p_parameter_value
			}
		};
	}

	/**
	 * 
	 * @desc function compares the IP address of two hosts
	 * @param p_host1 hostname
	 * @param p_host2 hostname
	 * @return boolean value that is true if the IP addresses are identical
	 * @verdict 
	 */	
 	function f_equivalentHostAddr(in charstring p_host1,  in charstring p_host2) return boolean
	{
	  //A DNS server may be used
	  return(fx_getIpAddr(p_host1) == fx_getIpAddr(p_host2));
	}


	/**
		* 
		* @desc function checks if Require contains Precondition
		* @param p_message (request or response) SIP message to be analysed
		* @return true if p_id parameter exist
		*/
	function f_checkRequirePrecondition(in Request p_message)
	{
		if (ispresent(p_message.msgHeader.require))
		{
			var boolean v_precondition_found:=false;
			for (var integer v_i:=0; v_i<sizeof(p_message.msgHeader.require.optionsTags); v_i:=v_i+1){			
				if (match(p_message.msgHeader.require.optionsTags[v_i],c_tagPrecond)) {
					v_precondition_found:=true;
				}
			}
			if (not(v_precondition_found)){
				setverdict(fail);
				log("FAIL: precondition not found in Require options list!");
			}
		} 
		else
		{
			setverdict(fail);
			log("FAIL: Require options is not present!");
		}
	}

	/**
	 * 
	 * @desc function checks if P-Charging-Vector contains a particular parameter
	 * @param p_message (request or response) SIP message to be analysed
	 * @param p_id name of parameter
	 * @return true if p_id parameter exist
	 */
	function f_checkPChargingVectorHeaderParamId(in Request p_message, charstring p_id) return boolean
	{
	  var integer v_chargeParamsLen;
	  
	  if (ispresent(p_message.msgHeader.pChargingVector)) {		
		for (var integer i:=0; i<sizeof(p_message.msgHeader.pChargingVector.chargeParams); i:=i+1)
				{if(p_message.msgHeader.pChargingVector.chargeParams[i].id == p_id)
					{return (true)}
				};
	  }
	  return (false)
	}

	/**
	 * 
	 * @desc function checks if P-Charging-Vector contains a particular parameter
	 * @param p_message (request or response) SIP message to be analysed
	 * @param p_id name of parameter
	 * @return true if p_id parameter exist
	 */
	function f_checkPChargingVectorHeaderParamIdResponse(in Response p_message, charstring p_id) return boolean
	{
	  var integer v_chargeParamsLen;
	  
	  if (ispresent(p_message.msgHeader.pChargingVector)) {		
		for (var integer i:=0; i<sizeof(p_message.msgHeader.pChargingVector.chargeParams); i:=i+1)
				{if(p_message.msgHeader.pChargingVector.chargeParams[i].id == p_id)
					{return (true)}
				};
	  }
	  return (false)
	}

poglitsch's avatar
poglitsch committed
	/**
		* 
		* @desc function returns the Host/Port of a given Contact header field
		* @param p_contact contact header field to be analysed
		* @return Host/Port record  from the contact header field
		*/
	function f_getContactUri(in ContactAddress p_contact) runs on SipComponent return SipUrl
	{
		var SipUrl    v_SipUrl;
      
		if (ischosen(p_contact.addressField.nameAddr))
		{
				v_SipUrl := p_contact.addressField.nameAddr.addrSpec;
		}
		else
		{
				v_SipUrl := p_contact.addressField.addrSpecUnion;
		}
      
		return(v_SipUrl);
	} // end f_getContactUri

	 * 
	 * @desc function returns the Host/Port of a given Contact header field
	 * @param p_contact contact header field to be analysed
	 * @return Host/Port record  from the contact header field
	 */
	function f_getContactAddr(in ContactAddress p_contact) runs on SipComponent return HostPort
	  {
		var HostPort v_locAddr;
		var SipUrl    v_SipUrl;
      
		if (ischosen(p_contact.addressField.nameAddr))
		{
		  v_SipUrl := p_contact.addressField.nameAddr.addrSpec;
		}
		else
		{
		  v_SipUrl := p_contact.addressField.addrSpecUnion;
		}
      
		v_locAddr.host := v_SipUrl.components.sip.hostPort.host;
		if (ispresent(v_SipUrl.components.sip.hostPort.portField))
			v_locAddr.portField := v_SipUrl.components.sip.hostPort.portField;
		}
		else
		{
			v_locAddr.portField := c_defaultSipPort;
		}
      
		return(v_locAddr);
	  } // end f_getContactAddr

	/**
		* 
		* @desc function checks if History-Info-Header of the p_message contains a particular URI
		* @param p_message (request or response) SIP message to be analysed
		* @param p_URI name of parameter
		* @return true if p_URI parameter exist
		*/
	function f_checkHeaderInfoURI(in Response p_message, SipUrl p_URI) return boolean
	{
			var integer v_chargeParamsLen;
	  
			if (ispresent(p_message.msgHeader.historyInfo)) {		
		for (var integer i:=0; i<sizeof(p_message.msgHeader.historyInfo.historyInfoList); i:=i+1)
				{if(p_message.msgHeader.historyInfo.historyInfoList[i].nameAddr.addrSpec == p_URI)
					{return (true)}
				};
			}
			return (false)
	}
	
	/**
	* 
	* @desc function returns the Userinfo from  a given To header field
	* @param p_to To header field to be analysed
	* @return Userinfo from the To header field as a charstring
	*/
	function f_getUserfromTo(in To p_to) runs on SipComponent return charstring
	{
		var SipUrl    v_SipUrl;
  
  		if (ischosen(p_to.addressField.nameAddr))
		{
			v_SipUrl := p_to.addressField.nameAddr.addrSpec;
		}
		else
		{
			v_SipUrl := p_to.addressField.addrSpecUnion;
		}
  
		return(v_SipUrl.components.sip.userInfo.userOrTelephoneSubscriber);
	} // end f_getUserfromTo

	/**
	 * 
	 * @desc function to generate a 32 bits random number as a charstring for tag field
	 * @param p_cSeq_s CSeq parameter used to modify the tag field value
	 * @return tag value
	 */
	function f_getRndCallId(inout CSeq p_cSeq_s) return charstring
	{
	  var charstring v_tag_value;
	  v_tag_value := fx_rndStr()&fx_rndStr();
	  //v_tag_value is initialized with a random value with at least 32 bits of randomness
	  // 4294967296 is a 32 bits integer
	  //v_tag_value := int2str(float2int(4294967296.0*rnd()) + loc_CSeq_s.seqNumber );
	  return(v_tag_value);
	}

	/**
	 * 
	 * @desc function give access to the top element of the Path header field.
	 * @param p_Request SIP message to be analysed
	 * @return NameAddr (e.g. <sip:p.home.com>) or omit
	 */
rennoch's avatar
rennoch committed
	function f_getPathHeaderTop(inout Request p_Request) return template NameAddr
	{
	  if (ispresent(p_Request.msgHeader.path)) {
	  	if (sizeof(p_Request.msgHeader.path.pathValues)>0) {
			return(p_Request.msgHeader.path.pathValues[0].nameAddr)}
	  	};
	  return(omit)
	}

	/**
	 * 
	 * @desc function updates first element of a Via headerfield list 
	 * @param p_viaBody_List address list of a Via header field
	 * @param p_source_address address to be inserted in the top element
	 */
	function f_getViaReplyAddr(inout ViaBody_List p_viaBody_List, inout address4SIP p_source_address)
	 runs on SipComponent 
	 {	
	   var ViaBody  v_viaBody;
	   var HostPort v_locAddr;
	   // The address to send message shall be updated after getting information
	   // in the Via header fied and according to 18.2.2
	   v_viaBody := p_viaBody_List[0];
      
	   // received parameter has to be addded to the via hader field
	   // Be careful it could be an Host name and not an IP Address

	   // TODO produce an error because of unkown host exception
	   //if (not f_equivalentHostAddr(valueof (v_viaBody.sentBy.host),
	   //	   valueof (p_source_address.host))) {
		   f_addParameterIfNotPresent(
			   c_receivedId,
			   valueof (p_source_address.host),
			   v_viaBody);
	   if (ispresent(v_viaBody.sentBy.portField))
	   {
		 p_source_address.portField := valueof(v_viaBody.sentBy.portField);
	   }
	   else
	   {
		 p_source_address.portField := c_defaultSipPort;
	   }
	 }
 
	/**
	 * 
	 * @desc functions give access to an element of the Route header field (record).
	 * @param p_message (request) SIP message to be analysed
	 * @param p_index index of Route record element to be retrieved
	 * @return HostPort value of the Route element or omit
	 */
	function f_getRouteHeaderElementAddressFromRequest(in Request p_message, in integer p_index) return HostPort
	{
	  if (ispresent(p_message.msgHeader.route)) {
		if (sizeof(p_message.msgHeader.route.routeBody)>p_index) {
			return(p_message.msgHeader.route.routeBody[p_index].nameAddr.addrSpec.components.sip.hostPort)}
		};
	setverdict(fail);
	return(c_hostport_dummy)
	}

	/**
	 * 
	 * @desc functions give access to an element of the Record-Route header field (record).
	 * @param p_message (request) SIP message to be analysed
	 * @param p_index index of recordRoute record element to be retrieved
	 * @return HostPort value of the Record-Route element or omit
	 */
	function f_getRecordRouteHeaderElementAddressFromRequest(in Request p_message, in integer p_index) return HostPort
	{
	  if (ispresent(p_message.msgHeader.recordRoute)) {
		if (sizeof(p_message.msgHeader.recordRoute.routeBody)>p_index) {
			return(p_message.msgHeader.recordRoute.routeBody[p_index].nameAddr.addrSpec.components.sip.hostPort)}
		};
	setverdict(fail);
	return(c_hostport_dummy)
	}
    
	/**
	 * 
	 * @desc functions give access to an element of the Record-Route header field (record).
	 * @param p_message (response) SIP message to be analysed
	 * @param p_index index of recordRoute record element to be retrieved
	 * @return HostPort value of the Record-Route element or omit
	 */
	function f_getRecordRouteHeaderElementAddressFromResponse(in Response p_message, in integer p_index) return HostPort
	{
	  if (ispresent(p_message.msgHeader.recordRoute)) {
		if (sizeof(p_message.msgHeader.recordRoute.routeBody)>p_index) {
			return(p_message.msgHeader.recordRoute.routeBody[p_index].nameAddr.addrSpec.components.sip.hostPort)}
		};
	setverdict(fail);
	return(c_hostport_dummy)
	}
    
	/**
	 * 
	 * @desc functions give access to an element of the Via header field (record).
	 * @param p_message (request) SIP message to be analysed
 	 * @param p_index index of via record element to be retrieved
 	 * @return HostPort value of the Via element or omit
	 */
	function f_getViaHeaderElementHostPort(in Request p_message, in integer p_index) return HostPort
	{
	
		if (sizeof(p_message.msgHeader.via.viaBody)>p_index) {
			return(p_message.msgHeader.via.viaBody[p_index].sentBy)}
	setverdict(fail);
	return(c_hostport_dummy)
	}
	
	/**
	 * 
	 * @desc functions give access to an element of the Via header field (record).
	 * @param p_message (response) SIP message to be analysed
	 * @param p_index index of via record element to be retrieved
	 * @return HostPort value of the Via element or omit
	 */	function f_getViaHeaderElementHostPortResponse(in Response p_message, in integer p_index) return HostPort
	{
	
		if (sizeof(p_message.msgHeader.via.viaBody)>p_index) {
			return(p_message.msgHeader.via.viaBody[p_index].sentBy)}
	setverdict(fail);
	return(c_hostport_dummy)
	}	
	
	/**
	 * 
	 * @desc function checks indicators if topology hiding (TH) has been applied:
	 *	- second element in via-header record has tokenized-by parameter
	 * @param p_Request SIP message to be analysed
	 * @return boolean value (true indicate TH, false otherwise)
	 */
	function f_topologyHiding(inout Request p_request) runs on SipComponent return boolean
	{ var GenericParam v_viaParameter;
	    if (sizeof(p_request.msgHeader.via.viaBody)<2)
         {return(false)};
	  v_viaParameter := p_request.msgHeader.via.viaBody[1].viaParams[0]; // second element
	  if (not v_viaParameter.id == "tokenized-by") 
		 {return(false)};
	  return(true)
	}

	/**
	 * 
	 * @desc function checks indicators if topology hiding (TH) has been applied:
	 *	- any element in via-header record has tokenized-by parameter
	 * @param Response SIP message to be analysed
	 * @return boolean value (true indicate TH, false otherwise)
	 */
	function f_topologyHidingResponse(inout Response p_response) runs on SipComponent return boolean
	{ 
	 var GenericParam v_viaParameter;
	log(p_response.msgHeader);
	 for (var integer v_i := 0; v_i < sizeof(p_response.msgHeader.via.viaBody); v_i := v_i + 1) {
		
	  v_viaParameter := p_response.msgHeader.via.viaBody[v_i].viaParams[0]; // first parameter

	  if (not v_viaParameter.id == "tokenized-by") 
		 {return(false)}
	 }
	 return(true);
	
	}
	


group SetHeaders {


	/**
	 * @desc function for setting of component variables related to message header fields 
	 *		(message type independent: CSeq, contact, via), function uses information from userprofile
	 *		
	 * @param p_cSeq_s CSeq parameter
	 * @param p_method method name for cSeq header field
	 */	
 	function f_setHeadersGeneral(inout CSeq p_cSeq_s, in charstring p_method) runs on SipComponent
	{
	  p_cSeq_s.fieldName := CSEQ_E;
	  p_cSeq_s.seqNumber := p_cSeq_s.seqNumber + 1;
	  p_cSeq_s.method    := p_method ;
	  vc_cSeq := p_cSeq_s;
      
	  vc_contact := valueof(m_Contact(m_SipUrl_contactIpaddr(vc_userprofile)));
garciay's avatar
garciay committed

	  vc_branch := c_branchCookie & f_getRndTag();
	  vc_via:={
		fieldName := VIA_E,
		viaBody 	 := {valueof(m_ViaBody_currIpaddr(vc_branch, vc_userprofile))}
	  };