| module SIP_Templates { |
| |
| import from SIPmsg_Types all; |
| import from TCCConversion_Functions all; |
| import from TCCOpenSecurity_Functions all; |
| import from TCCDateTime_Functions all; |
| import from Native_Functions all; |
| import from Osmocom_Types all; |
| import from Misc_Helpers all; |
| |
| /* wrapper type to encapsulate the Addr_Union + parameter list used in From, To. ... */ |
| type record SipAddr { |
| Addr_Union addr, |
| SemicolonParam_List params optional |
| } |
| |
| const charstring c_SIP_VERSION := "SIP/2.0"; |
| |
| template (value) GenericParam ts_Param(template (value) charstring id, |
| template (omit) charstring paramValue := omit) := { |
| id := id, |
| paramValue := paramValue |
| } |
| template (present) GenericParam tr_Param(template (present) charstring id := ?, |
| template charstring paramValue := *) := { |
| id := id, |
| paramValue := paramValue |
| } |
| function f_ts_Param_omit(template (value) charstring id, |
| template (omit) charstring paramValue := omit) |
| return template (omit) GenericParam |
| { |
| if (istemplatekind(paramValue, "omit")) { |
| return omit; |
| } |
| return ts_Param(id, paramValue); |
| } |
| |
| template (value) SipUrl ts_SipUrl(template (value) HostPort host_port, |
| template (omit) UserInfo user_info := omit) := { |
| scheme := "sip", |
| userInfo := user_info, |
| hostPort := host_port, |
| urlParameters := omit, |
| headers := omit |
| } |
| template (present) SipUrl tr_SipUrl(template (present) HostPort host_port := ?, |
| template UserInfo user_info := *) := { |
| scheme := "sip", |
| userInfo := user_info, |
| hostPort := host_port, |
| urlParameters := *, |
| headers := * |
| } |
| |
| template (value) SipUrl ts_SipUrlHost(template (value) charstring host, |
| template (omit) integer portField := omit) |
| := ts_SipUrl(ts_HostPort(host, portField)); |
| |
| function ts_SipUrl_from_Addr_Union(template (value) Addr_Union au) |
| return template (value) SipUrl { |
| if (ischosen(au.nameAddr)) { |
| return au.nameAddr.addrSpec; |
| } else { /* au.addrSpecUnion */ |
| return au.addrSpecUnion; |
| } |
| } |
| |
| // [20.5] |
| template (present) Allow tr_Allow(template Method_List methods := *) := { |
| fieldName := ALLOW_E, |
| methods := methods |
| } |
| template (value) Allow ts_Allow(template (omit) Method_List methods := omit) := { |
| fieldName := ALLOW_E, |
| methods := methods |
| } |
| |
| template (present) Credentials tr_Credentials_DigestResponse(template (present) CommaParam_List digestResponse) := { |
| digestResponse := digestResponse |
| } |
| template (value) Credentials ts_Credentials_DigestResponse(template (value) CommaParam_List digestResponse) := { |
| digestResponse := digestResponse |
| } |
| |
| template (value) Credentials ts_Credentials_DigestResponseMD5( |
| template (value) charstring username, |
| template (value) charstring realm, |
| template (value) charstring nonce, |
| template (value) charstring uri, |
| template (value) charstring response, |
| template (value) charstring opaque, |
| template (value) charstring algorithm := "MD5", |
| template (value) charstring qop := "auth", |
| template (omit) charstring cnonce := omit, |
| template (omit) charstring nc := omit |
| ) := { |
| digestResponse := { |
| // Already added by digestResponse automatically: |
| //ts_Param("Digest", omit), |
| ts_Param("username", f_sip_str_quote(username)), |
| ts_Param("realm", f_sip_str_quote(realm)), |
| ts_Param("nonce", f_sip_str_quote(nonce)), |
| ts_Param("uri", f_sip_str_quote(uri)), |
| ts_Param("response", f_sip_str_quote(response)), |
| ts_Param("opaque", f_sip_str_quote(opaque)), |
| ts_Param("algorithm", algorithm), |
| ts_Param("qop", qop), |
| // FIXME: If "omit" is passed, these below end up in; |
| // "Dynamic test case error: Performing a valueof or send operation on a non-specific template of type @SIPmsg_Types.GenericParam" |
| f_ts_Param_omit("cnonce", f_sip_str_quote(cnonce)), |
| f_ts_Param_omit("nc", nc) |
| } |
| } |
| |
| template (value) Credentials ts_Credentials_OtherAuth(template (value) OtherAuth otherResponse) := { |
| otherResponse := otherResponse |
| } |
| |
| template (present) Authorization tr_Authorization(template (present) Credentials body) := { |
| fieldName := AUTHORIZATION_E, |
| body := body |
| } |
| template (value) Authorization ts_Authorization(template (value) Credentials body) := { |
| fieldName := AUTHORIZATION_E, |
| body := body |
| } |
| |
| // [20.10] |
| template (present) NameAddr tr_NameAddr(template (present) SipUrl addrSpec := ?, |
| template charstring displayName := *) := { |
| displayName := displayName, |
| addrSpec := addrSpec |
| } |
| template (value) NameAddr ts_NameAddr(template (value) SipUrl addrSpec, |
| template (omit) charstring displayName := omit) := { |
| displayName := displayName, |
| addrSpec := addrSpec |
| } |
| |
| template (present) Addr_Union tr_Addr_Union_NameAddr(template (present) NameAddr nameAddr := ?) := { |
| nameAddr := nameAddr |
| } |
| template (value) Addr_Union ts_Addr_Union_NameAddr(template (value) NameAddr nameAddr) := { |
| nameAddr := nameAddr |
| } |
| |
| template (present) Addr_Union tr_Addr_Union_SipUrl(template (present) SipUrl sipUrl := ?) := { |
| addrSpecUnion := sipUrl |
| } |
| template (value) Addr_Union ts_Addr_Union_SipUrl(template (value) SipUrl sipUrl) := { |
| addrSpecUnion := sipUrl |
| } |
| |
| |
| template (present) ContactAddress tr_ContactAddress(template (present) Addr_Union addressField := ?, |
| template SemicolonParam_List contactParams := *) := { |
| addressField := addressField, |
| contactParams := contactParams |
| } |
| template (value) ContactAddress ts_ContactAddress(template (value) Addr_Union addressField, |
| template (omit) SemicolonParam_List contactParams := omit) := { |
| addressField := addressField, |
| contactParams := contactParams |
| } |
| |
| template (present) Contact tr_Contact(template (present) ContactAddress_List contactAddresses := ?) := { |
| fieldName := CONTACT_E, |
| contactBody := { |
| contactAddresses := contactAddresses |
| } |
| } |
| template (value) Contact ts_Contact(template (value) ContactAddress_List contactAddresses) := { |
| fieldName := CONTACT_E, |
| contactBody := { |
| contactAddresses := contactAddresses |
| } |
| } |
| |
| template (value) Contact ts_ContactWildcard := { |
| fieldName := CONTACT_E, |
| contactBody := { |
| wildcard := "*" |
| } |
| } |
| |
| template (present) Contact tr_Contact_SipAddr(template (present) SipAddr contact_addr := ?) |
| := tr_Contact({ tr_ContactAddress(contact_addr.addr, contact_addr.params) }); |
| |
| private function f_tr_Contact_SipAddr(template SipAddr contact_addr) return template Contact |
| { |
| if (istemplatekind(contact_addr, "omit")) { |
| return omit; |
| } else if (istemplatekind(contact_addr, "*")) { |
| return *; |
| } |
| return tr_Contact_SipAddr(contact_addr); |
| } |
| |
| template (value) Contact ts_Contact_SipAddr(template (value) SipAddr contact_addr) |
| := ts_Contact({ ts_ContactAddress(contact_addr.addr, contact_addr.params) }); |
| private function ts_Contact_SipAddr_omit(template (omit) SipAddr contact_addr := omit) return template (omit) Contact |
| { |
| if (istemplatekind(contact_addr, "omit")) { |
| return omit; |
| } |
| return ts_Contact_SipAddr(contact_addr); |
| } |
| |
| |
| // [20.14] |
| template (value) ContentLength ts_ContentLength(template (value) integer len := 0) := { |
| fieldName := CONTENT_LENGTH_E, |
| len := len |
| } |
| template (present) ContentLength tr_ContentLength(template (present) integer len := ?) := { |
| fieldName := CONTENT_LENGTH_E, |
| len := len |
| } |
| |
| // [20.19] |
| template (value) Expires ts_Expires(template (value) DeltaSec deltaSec := "7200") := { |
| fieldName := EXPIRES_E, |
| deltaSec := deltaSec |
| } |
| |
| // [RFC3455 5.4] + 3GPP 24.229 V8.7.0 |
| template (present) Access_net_spec tr_Access_net_spec(template (present) charstring access_type := ?, |
| template SemicolonParam_List access_info := *) := { |
| access_type := access_type, |
| access_info := access_info |
| } |
| template (present) Access_net_spec tr_Access_net_spec_EUTRAN(template (present) charstring uli_str := ?) := { |
| access_type := "3GPP-E-UTRAN-FDD", |
| access_info := {tr_Param("utran-cell-id-3gpp", uli_str)} |
| } |
| |
| // [RFC3455 5.4] + 3GPP 24.229 V8.7.0 |
| template (present) P_Access_Network_Info tr_P_Access_Network_Info(template (present) Access_net_spec_list access_net_specs := ?) := { |
| fieldName := P_ACCESS_NETWORK_INFO, |
| access_net_specs := access_net_specs |
| } |
| |
| |
| // [20.32] |
| template (value) Require ts_Require(template (value) OptionTag_List optionsTags := {}) := { |
| fieldName := REQUIRE_E, |
| optionsTags := optionsTags |
| } |
| template (present) Require tr_Require(template (present) OptionTag_List optionsTags := ?) := { |
| fieldName := REQUIRE_E, |
| optionsTags := optionsTags |
| } |
| |
| // [20.35 RFC2616 14.38] |
| template (value) Server ts_Server(template (value) ServerVal_List serverBody := {}) := { |
| fieldName := SERVER_E, |
| serverBody := serverBody |
| } |
| template (present) Server tr_Server(template (present) ServerVal_List serverBody := ?) := { |
| fieldName := SERVER_E, |
| serverBody := serverBody |
| } |
| |
| // [20.37] |
| template (value) Supported ts_Supported(template (value) OptionTag_List optionsTags := {}) := { |
| fieldName := SUPPORTED_E, |
| optionsTags := optionsTags |
| } |
| template (present) Supported tr_Supported(template (present) OptionTag_List optionsTags := ?) := { |
| fieldName := SUPPORTED_E, |
| optionsTags := optionsTags |
| } |
| |
| // [20.41 RFC2616 14.43] |
| template (value) UserAgent ts_UserAgent(template (value) ServerVal_List userAgentBody := {}) := { |
| fieldName := USER_AGENT_E, |
| userAgentBody := userAgentBody |
| } |
| template (present) UserAgent tr_UserAgent(template (present) ServerVal_List userAgentBody := ?) := { |
| fieldName := USER_AGENT_E, |
| userAgentBody := userAgentBody |
| } |
| |
| |
| template (value) SipAddr ts_SipAddr(template (value) HostPort host_port, |
| template (omit) UserInfo user_info := omit, |
| template (omit) charstring displayName := omit, |
| template (omit) SemicolonParam_List params := omit) := { |
| addr := { |
| nameAddr := { |
| displayName := displayName, |
| addrSpec := ts_SipUrl(host_port, user_info) |
| } |
| }, |
| params := params |
| } |
| template (present) SipAddr tr_SipAddr(template (present) HostPort host_port := ?, |
| template UserInfo user_info := *, |
| template charstring displayName := *, |
| template SemicolonParam_List params := *) := { |
| addr := { |
| nameAddr := { |
| displayName := displayName, |
| addrSpec := tr_SipUrl(host_port, user_info) |
| } |
| }, |
| params := params |
| } |
| |
| /* build a receive template from a value: substitute '*' for omit */ |
| function tr_SipUrl_from_val(template (value) SipUrl tin) return template (present) SipUrl { |
| var template (present) SipUrl ret := tin; |
| |
| /* if the port number is 5060, it may be omitted */ |
| if (ispresent(tin.hostPort.portField) and |
| valueof(tin.hostPort.portField) == 5060) { |
| ret.hostPort.portField := 5060 ifpresent; |
| } |
| if (not ispresent(tin.userInfo.password)) { |
| ret.userInfo.password := *; |
| } |
| |
| return ret; |
| } |
| function tr_SipAddr_from_val(template (value) SipAddr tin) return template (present) SipAddr { |
| var template (present) SipAddr ret := tin; |
| |
| if (not ispresent(tin.addr.nameAddr.displayName)) { |
| ret.addr.nameAddr.displayName := *; |
| } else if (f_str_tolower(f_sip_str_unquote(tin.addr.nameAddr.displayName)) == "anonymous") { |
| /* if the user is Anonymous, it may be omitted */ |
| ret.addr.nameAddr.displayName := tin.addr.nameAddr.displayName ifpresent; |
| } |
| |
| ret.addr.nameAddr.addrSpec := tr_SipUrl_from_val(tin.addr.nameAddr.addrSpec); |
| |
| if (not ispresent(tin.params)) { |
| ret.params := *; |
| } |
| return ret; |
| } |
| |
| function ts_SipAddr_from_Addr_Union(template (value) Addr_Union au, |
| template (omit) SemicolonParam_List params := omit) |
| return template (value) SipAddr { |
| var template (value) SipUrl addrSpec := ts_SipUrl_from_Addr_Union(au); |
| var template (omit) charstring displayName; |
| |
| if (ischosen(au.nameAddr)) { |
| displayName := au.nameAddr.displayName; |
| } else { /* au.addrSpecUnion */ |
| displayName := omit |
| } |
| |
| return ts_SipAddr(addrSpec.hostPort, |
| addrSpec.userInfo, |
| displayName, |
| params); |
| } |
| |
| template (value) HostPort ts_HostPort(template (omit) charstring host := omit, |
| template (omit) integer portField := omit) := { |
| host := host, |
| portField := portField |
| } |
| |
| template (present) HostPort tr_HostPort(template charstring host := *, |
| template integer portField := *) := { |
| host := host, |
| portField := portField |
| } |
| function f_tr_HostPort(template charstring host := *, |
| template integer portField := *) |
| return template (present) HostPort { |
| return f_tr_HostPort_opt_defport(tr_HostPort(host, portField)); |
| } |
| function f_tr_HostPort_opt_defport(template (present) HostPort hp) return template (present) HostPort { |
| var template (present) HostPort hpout := hp; |
| /* if the port number is 5060, it may be omitted */ |
| if (isvalue(hp.portField) and valueof(hp.portField) == 5060) { |
| hpout.portField := 5060 ifpresent; |
| } |
| return hpout; |
| } |
| |
| function f_tr_SipUrl_opt_defport(template (present) SipUrl url) return template (present) SipUrl { |
| var template (present) SipUrl urlout := url; |
| urlout.hostPort := f_tr_HostPort_opt_defport(url.hostPort); |
| return urlout; |
| } |
| |
| template (value) UserInfo ts_UserInfo(template (value) charstring userOrTelephoneSubscriber, |
| template (omit) charstring password := omit) := { |
| userOrTelephoneSubscriber := userOrTelephoneSubscriber, |
| password := password |
| } |
| template (present) UserInfo tr_UserInfo(template (present) charstring userOrTelephoneSubscriber := ?, |
| template charstring password := *) := { |
| userOrTelephoneSubscriber := userOrTelephoneSubscriber, |
| password := password |
| } |
| |
| template (value) RequestLine ts_SIP_ReqLine(Method method, |
| template (value) SipUrl uri, |
| charstring ver := c_SIP_VERSION) := { |
| method := method, |
| requestUri := uri, |
| sipVersion := ver |
| } |
| template (present) RequestLine tr_SIP_ReqLine(template (present) Method method := ?, |
| template (present) SipUrl uri := ?, |
| template (present) charstring ver := c_SIP_VERSION) := { |
| method := method, |
| requestUri := uri, |
| sipVersion := ver |
| } |
| |
| template (value) StatusLine ts_SIP_StatusLine(integer status_code, charstring reason) := { |
| sipVersion := "SIP/2.0", |
| statusCode := status_code, |
| reasonPhrase := reason |
| } |
| template (present) StatusLine tr_SIP_StatusLine(template integer status_code, |
| template charstring reason) := { |
| sipVersion := "SIP/2.0", |
| statusCode := status_code, |
| reasonPhrase := reason |
| } |
| |
| |
| template (value) PDU_SIP_Request ts_SIP_req(template (value) RequestLine rl) := { |
| requestLine := rl, |
| msgHeader := c_SIP_msgHeader_empty, |
| messageBody := omit, |
| payload := omit |
| } |
| |
| const Method_List c_SIP_defaultMethods := { |
| "INVITE", "ACK", "BYE", "CANCEL", "OPTIONS", "PRACK", "MESSAGE", "SUBSCRIBE", |
| "NOTIFY", "REFER", "UPDATE" }; |
| |
| private function f_ContentTypeOrOmit(template (omit) ContentType ct, template (omit) charstring body) |
| return template (omit) ContentType { |
| /* if user explicitly stated no content type */ |
| if (istemplatekind(ct, "omit")) { |
| return omit; |
| } |
| /* if there's no body, then there's no content-type either */ |
| if (istemplatekind(body, "omit")) { |
| return omit; |
| } |
| return ct; |
| } |
| |
| private function f_ContentLength(template (omit) charstring body) |
| return template (value) ContentLength { |
| /* rfc3261 20.14: "If no body is present in a message, then the |
| * Content-Length header field value MUST be set to zero." */ |
| if (istemplatekind(body, "omit")) { |
| return ts_ContentLength(0); |
| } |
| return ts_ContentLength(lengthof(body)); |
| } |
| |
| template (value) ContentType ts_CT_SDP := { |
| fieldName := CONTENT_TYPE_E, |
| mediaType := "application/sdp" |
| }; |
| |
| template (value) Via ts_Via_from(template (value) HostPort addr, |
| template (value) charstring transport := "UDP") := { |
| fieldName := VIA_E, |
| viaBody := { |
| { |
| sentProtocol := { "SIP", "2.0", transport }, |
| sentBy := addr, |
| viaParams := omit |
| } |
| } |
| } |
| template (present) Via tr_Via_from(template (present) HostPort host_port := ?, |
| template (present) charstring transport := ?, |
| template SemicolonParam_List viaParams := *) := { |
| fieldName := VIA_E, |
| viaBody := { |
| { |
| sentProtocol := { "SIP", "2.0", ? }, |
| sentBy := host_port, |
| viaParams := viaParams |
| } |
| } |
| } |
| |
| template (present) OtherAuth |
| tr_OtherAuth(template (present) charstring authScheme := ?, |
| template (present) CommaParam_List authParams := ?) := { |
| authScheme := authScheme, |
| authParams := authParams |
| } |
| |
| template (value) OtherAuth |
| ts_OtherAuth(template (value) charstring authScheme, |
| template (value) CommaParam_List authParams) := { |
| authScheme := authScheme, |
| authParams := authParams |
| } |
| |
| template (present) Challenge |
| tr_Challenge_digestCln(template (present) CommaParam_List digestCln := ?) := { |
| digestCln := digestCln |
| } |
| |
| template (value) Challenge |
| ts_Challenge_digestCln(template (value) CommaParam_List digestCln) := { |
| digestCln := digestCln |
| } |
| |
| template (present) Challenge |
| tr_Challenge_otherChallenge(template (present) OtherAuth otherChallenge := ?) := { |
| otherChallenge := otherChallenge |
| } |
| |
| template (value) Challenge |
| ts_Challenge_otherChallenge(template (value) OtherAuth otherChallenge) := { |
| otherChallenge := otherChallenge |
| } |
| |
| template (present) WwwAuthenticate |
| tr_WwwAuthenticate(template (present) Challenge_list challenge := ?) := { |
| fieldName := WWW_AUTHENTICATE_E, |
| challenge := challenge |
| } |
| |
| template (value) WwwAuthenticate |
| ts_WwwAuthenticate(template (value) Challenge_list challenge) := { |
| fieldName := WWW_AUTHENTICATE_E, |
| challenge := challenge |
| } |
| |
| // RFC3329 |
| template (present) Security_client |
| tr_Security_client(template (present) Security_mechanism_list sec_mechanism_list := ?) := { |
| fieldName := SECURITY_CLIENT_E, |
| sec_mechanism_list := sec_mechanism_list |
| } |
| template (value) Security_client |
| ts_Security_client(template (value) Security_mechanism_list sec_mechanism_list) := { |
| fieldName := SECURITY_CLIENT_E, |
| sec_mechanism_list := sec_mechanism_list |
| } |
| |
| template (present) Security_server |
| tr_Security_server(template (present) Security_mechanism_list sec_mechanism_list := ?) := { |
| fieldName := SECURITY_SERVER_E, |
| sec_mechanism_list := sec_mechanism_list |
| } |
| template (value) Security_server |
| ts_Security_server(template (value) Security_mechanism_list sec_mechanism_list) := { |
| fieldName := SECURITY_SERVER_E, |
| sec_mechanism_list := sec_mechanism_list |
| } |
| |
| template (present) Security_mechanism |
| tr_Security_mechanism(template (present) charstring name := ?, |
| template SemicolonParam_List params := *) := { |
| mechanism_name := name, |
| mechanism_params := params |
| } |
| template (value) Security_mechanism |
| ts_Security_mechanism(template (value) charstring name, |
| template (omit) SemicolonParam_List params := omit) := { |
| mechanism_name := name, |
| mechanism_params := params |
| } |
| |
| template (value) MessageHeader ts_SIP_msgHeader_empty := c_SIP_msgHeader_empty; |
| template (value) MessageHeader |
| ts_SIP_msgh_std(template (value) CallidString call_id, |
| template (value) SipAddr from_addr, |
| template (value) SipAddr to_addr, |
| template (omit) Contact contact, |
| template (value) charstring method, |
| template (value) integer seq_nr, |
| template (value) Via via, |
| template (omit) ContentLength content_length := ts_ContentLength(0), |
| template (omit) ContentType content_type := omit, |
| template (omit)Authorization authorization := omit, |
| template (omit) Allow allow := ts_Allow(c_SIP_defaultMethods), |
| template (omit) Expires expires := omit, |
| template (omit) Require require := omit, |
| template (omit) Security_client security_client := omit, |
| template (omit) Security_server security_server := omit, |
| template (omit) Server server := omit, |
| template (omit) Supported supported := omit, |
| template (omit) UserAgent userAgent := ts_UserAgent({ "osmo-ttcn3-hacks/0.23" }), |
| template (omit) WwwAuthenticate wwwAuthenticate := omit |
| ) modifies ts_SIP_msgHeader_empty := { |
| allow := allow, |
| authorization := authorization, |
| callId := { |
| fieldName := CALL_ID_E, |
| callid := call_id |
| }, |
| contact := contact, |
| contentLength := content_length, |
| contentType := content_type, |
| cSeq := { |
| fieldName := CSEQ_E, |
| seqNumber := seq_nr, |
| method := method |
| }, |
| expires := expires, |
| fromField := { |
| fieldName := FROM_E, |
| addressField := from_addr.addr, |
| fromParams := from_addr.params |
| }, |
| require := require, |
| security_client := security_client, |
| security_server := security_server, |
| server := server, |
| supported := supported, |
| toField := { |
| fieldName := TO_E, |
| addressField := to_addr.addr, |
| toParams := to_addr.params |
| }, |
| userAgent := userAgent, |
| via := via, |
| wwwAuthenticate := wwwAuthenticate |
| } |
| |
| template (present) MessageHeader |
| tr_SIP_msgh_std(template CallidString call_id, |
| template SipAddr from_addr, |
| template SipAddr to_addr, |
| template Contact contact, |
| template (present) Via via := tr_Via_from(?), |
| template charstring method, |
| template integer seq_nr := ?, |
| template ContentLength content_length := *, |
| template ContentType content_type := *, |
| template Allow allow := *, |
| template Authorization authorization := *, |
| template Expires expires := *, |
| template Require require := *, |
| template Security_client security_client := *, |
| template Security_server security_server := *, |
| template Server server := *, |
| template Supported supported := *, |
| template UserAgent userAgent := *, |
| template WwwAuthenticate wwwAuthenticate := * |
| ) modifies t_SIP_msgHeader_any := { |
| allow := allow, |
| authorization := authorization, |
| callId := { |
| fieldName := CALL_ID_E, |
| callid := call_id |
| }, |
| contact := contact, |
| contentLength := content_length, |
| contentType := content_type, |
| cSeq := { |
| fieldName := CSEQ_E, |
| seqNumber := seq_nr, |
| method := method |
| }, |
| expires := expires, |
| fromField := { |
| fieldName := FROM_E, |
| addressField := from_addr.addr, |
| fromParams := from_addr.params |
| }, |
| require := require, |
| security_client := security_client, |
| security_server := security_server, |
| server := server, |
| supported := supported, |
| toField := { |
| fieldName := TO_E, |
| addressField := to_addr.addr, |
| toParams := to_addr.params |
| }, |
| userAgent := userAgent, |
| via := via, |
| wwwAuthenticate := wwwAuthenticate |
| } |
| |
| |
| template (value) PDU_SIP_Request |
| ts_SIP_REGISTER(template (value) SipUrl sip_url_host_port, |
| template (value) CallidString call_id, |
| template (value) SipAddr from_addr, |
| template (value) SipAddr to_addr, |
| template (value) Via via, |
| integer seq_nr, |
| template (omit) Contact contact, |
| template (omit) Expires expires, |
| template (omit) Authorization authorization := omit, |
| template (omit) Require require := omit, |
| template (omit) Security_client security_client := omit, |
| template (omit) Supported supported := omit, |
| template (omit) charstring body := omit) := { |
| requestLine := ts_SIP_ReqLine(REGISTER_E, sip_url_host_port), |
| msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact, |
| "REGISTER", seq_nr, via, |
| content_length := f_ContentLength(body), |
| content_type := f_ContentTypeOrOmit(ts_CT_SDP, body), |
| authorization := authorization, |
| expires := expires, |
| require := require, |
| security_client := security_client, |
| supported := supported), |
| messageBody := body, |
| payload := omit |
| } |
| template (present) PDU_SIP_Request |
| tr_SIP_REGISTER(template (present) SipUrl sip_url_host_port := ?, |
| template (present) CallidString call_id := ?, |
| template (present) SipAddr from_addr := ?, |
| template (present) SipAddr to_addr := ?, |
| template (present) Via via := tr_Via_from(f_tr_HostPort_opt_defport(?)), |
| template integer seq_nr := *, |
| template Authorization authorization := *, |
| template Contact contact := *, |
| template Expires expires := *, |
| template Require require := *, |
| template Security_client security_client := *, |
| template Supported supported := *, |
| template charstring body := *) := { |
| requestLine := tr_SIP_ReqLine(REGISTER_E, sip_url_host_port), |
| msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact, |
| via, "REGISTER", seq_nr, |
| authorization := authorization, |
| expires := expires, |
| require := require, |
| security_client := security_client, |
| supported := supported), |
| messageBody := body, |
| payload := omit |
| } |
| |
| template (value) PDU_SIP_Request |
| ts_SIP_INVITE(template (value) CallidString call_id, |
| template (value) SipAddr from_addr, |
| template (value) SipAddr to_addr, |
| template (value) Via via, |
| template (value) Contact contact, |
| integer seq_nr, |
| template (omit) charstring body := omit) := { |
| requestLine := ts_SIP_ReqLine(INVITE_E, to_addr.addr.nameAddr.addrSpec), |
| msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, contact, |
| "INVITE", seq_nr, |
| via, |
| content_length := f_ContentLength(body), |
| content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)), |
| messageBody := body, |
| payload := omit |
| } |
| template (present) PDU_SIP_Request |
| tr_SIP_INVITE(template (present) SipUrl uri, |
| template CallidString call_id, |
| template SipAddr from_addr, |
| template SipAddr to_addr, |
| template Via via := tr_Via_from(f_tr_HostPort_opt_defport(?)), |
| template integer seq_nr, |
| template charstring body) := { |
| requestLine := tr_SIP_ReqLine(INVITE_E, uri), |
| msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, ?, |
| via, "INVITE", seq_nr), |
| messageBody := body, |
| payload := omit |
| } |
| |
| template (value) PDU_SIP_Request |
| ts_SIP_BYE(CallidString call_id, |
| template (value) SipAddr from_addr, |
| template (value) SipAddr to_addr, |
| template (value) Via via, |
| integer seq_nr, |
| template (omit) charstring body) := { |
| requestLine := ts_SIP_ReqLine(BYE_E, to_addr.addr.nameAddr.addrSpec), |
| msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, "BYE", seq_nr, |
| via, |
| content_length := f_ContentLength(body), |
| content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)), |
| messageBody := body, |
| payload := omit |
| } |
| |
| template (present) PDU_SIP_Request |
| tr_SIP_BYE(template (present) SipUrl uri, |
| template CallidString call_id, |
| template SipAddr from_addr, |
| template SipAddr to_addr, |
| template Via via, |
| template integer seq_nr, |
| template charstring body := *) := { |
| requestLine := tr_SIP_ReqLine(BYE_E, uri), |
| msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, omit, |
| via, "BYE", seq_nr), |
| messageBody := body, |
| payload := omit |
| } |
| |
| |
| template (value) PDU_SIP_Request |
| ts_SIP_ACK(template (value) CallidString call_id, |
| template (value) SipAddr from_addr, |
| template (value) SipAddr to_addr, |
| template (value) Via via, |
| integer seq_nr, |
| template (omit) charstring body) := { |
| requestLine := ts_SIP_ReqLine(ACK_E, to_addr.addr.nameAddr.addrSpec), |
| msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, |
| ts_Contact_SipAddr(from_addr), |
| "ACK", seq_nr, |
| via, |
| content_length := f_ContentLength(body), |
| content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)), |
| messageBody := body, |
| payload := omit |
| } |
| template (present) PDU_SIP_Request |
| tr_SIP_ACK(template (present) SipUrl uri, |
| template CallidString call_id, |
| template SipAddr from_addr, |
| template SipAddr to_addr, |
| template Via via, |
| template integer seq_nr, |
| template charstring body) := { |
| requestLine := tr_SIP_ReqLine(ACK_E, uri), |
| msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *, |
| via, |
| "ACK", seq_nr), |
| messageBody := body, |
| payload := omit |
| } |
| |
| template (present) PDU_SIP_Request |
| tr_SIP_CANCEL(template (present) SipUrl uri, |
| template (present) CallidString call_id, |
| template (present) SipAddr from_addr, |
| template (present) SipAddr to_addr, |
| template (present) Via via, |
| template (present) integer seq_nr, |
| template charstring body := *) := { |
| requestLine := tr_SIP_ReqLine(CANCEL_E, uri), |
| msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *, |
| via, |
| "CANCEL", seq_nr), |
| messageBody := body, |
| payload := omit |
| } |
| |
| template (value) PDU_SIP_Response |
| ts_SIP_Response(template (value) CallidString call_id, |
| template (value) SipAddr from_addr, |
| template (value) SipAddr to_addr, |
| charstring method, |
| integer status_code, |
| integer seq_nr, |
| charstring reason, |
| Via via, |
| template (omit) Allow allow := omit, |
| template (omit) Require require := omit, |
| template (omit) Server server := omit, |
| template (omit) Supported supported := omit, |
| template (omit) UserAgent userAgent := omit, |
| template (omit) charstring body := omit) := { |
| statusLine := ts_SIP_StatusLine(status_code, reason), |
| msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr, |
| via, |
| content_length := f_ContentLength(body), |
| content_type := f_ContentTypeOrOmit(ts_CT_SDP, body), |
| allow := allow, |
| require := require, |
| server := server, |
| supported := supported, |
| userAgent := userAgent), |
| messageBody := body, |
| payload := omit |
| } |
| /* 100 Trying */ |
| template (value) PDU_SIP_Response |
| ts_SIP_Response_Trying( |
| template (value) CallidString call_id, |
| template (value) SipAddr from_addr, |
| template (value) SipAddr to_addr, |
| Via via, |
| integer seq_nr, |
| charstring method := "INVITE", |
| template (omit) Allow allow := omit, |
| template (omit) Server server := omit, |
| template (omit) UserAgent userAgent := omit, |
| template (omit) charstring body := omit) := { |
| statusLine := ts_SIP_StatusLine(100, "Trying"), |
| msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr, |
| via, |
| content_length := f_ContentLength(body), |
| content_type := f_ContentTypeOrOmit(ts_CT_SDP, body), |
| allow := allow, |
| server := server, |
| userAgent := userAgent), |
| messageBody := body, |
| payload := omit |
| } |
| /* 180 Ringing */ |
| template (value) PDU_SIP_Response |
| ts_SIP_Response_Ringing( |
| template (value) CallidString call_id, |
| template (value) SipAddr from_addr, |
| template (value) SipAddr to_addr, |
| Via via, |
| integer seq_nr, |
| charstring method := "INVITE", |
| template (omit) charstring body := omit) := { |
| statusLine := ts_SIP_StatusLine(180, "Ringing"), |
| msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr, |
| via, |
| content_length := f_ContentLength(body), |
| content_type := f_ContentTypeOrOmit(ts_CT_SDP, body)), |
| messageBody := body, |
| payload := omit |
| } |
| |
| /* 401 Unauthorized */ |
| template (value) PDU_SIP_Response |
| ts_SIP_Response_Unauthorized( |
| template (value) CallidString call_id, |
| template (value) SipAddr from_addr, |
| template (value) SipAddr to_addr, |
| Via via, |
| template (value) WwwAuthenticate wwwAuthenticate, |
| integer seq_nr, |
| charstring method := "REGISTER", |
| template (omit) Allow allow := omit, |
| template (omit) Security_server security_server := omit, |
| template (omit) Server server := omit, |
| template (omit) Supported supported := omit, |
| template (omit) UserAgent userAgent := omit, |
| template (omit) charstring body := omit) := { |
| statusLine := ts_SIP_StatusLine(401, "Unauthorized"), |
| msgHeader := ts_SIP_msgh_std(call_id, from_addr, to_addr, omit, method, seq_nr, |
| via, |
| content_length := f_ContentLength(body), |
| content_type := f_ContentTypeOrOmit(ts_CT_SDP, body), |
| allow := allow, |
| security_server := security_server, |
| server := server, |
| supported := supported, |
| userAgent := userAgent, |
| wwwAuthenticate := wwwAuthenticate), |
| messageBody := body, |
| payload := omit |
| } |
| |
| template (present) PDU_SIP_Response |
| tr_SIP_Response(template CallidString call_id, |
| template SipAddr from_addr, |
| template SipAddr to_addr, |
| template (present) Via via := tr_Via_from(?), |
| template Contact contact, |
| template charstring method, |
| template integer status_code, |
| template integer seq_nr := ?, |
| template charstring reason := ?, |
| template charstring body := *) := { |
| statusLine := tr_SIP_StatusLine(status_code, reason), |
| msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact, |
| via, |
| method, seq_nr), |
| messageBody := body, |
| payload := omit |
| } |
| |
| /* Expect during first REGISTER/INVITE/... when authorization is required: */ |
| template (present) PDU_SIP_Response |
| tr_SIP_Response_Unauthorized( |
| template CallidString call_id, |
| template SipAddr from_addr, |
| template SipAddr to_addr, |
| template (present) Via via := tr_Via_from(?), |
| template Contact contact := *, |
| template (present) WwwAuthenticate wwwAuthenticate := ?, |
| template integer seq_nr := ?, |
| template charstring method := "REGISTER", |
| template integer status_code := 401, |
| template charstring reason := "Unauthorized", |
| template charstring body := *) := { |
| statusLine := tr_SIP_StatusLine(status_code, reason), |
| msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, contact, |
| via, |
| method, seq_nr, |
| wwwAuthenticate := wwwAuthenticate), |
| messageBody := body, |
| payload := omit |
| } |
| |
| /* 100 Trying */ |
| template (present) PDU_SIP_Response |
| tr_SIP_Response_Trying( |
| template CallidString call_id, |
| template SipAddr from_addr, |
| template SipAddr to_addr, |
| template (present) Via via := tr_Via_from(?), |
| template integer seq_nr := ?, |
| template charstring method := "INVITE", |
| template integer status_code := 100, |
| template charstring reason := "Trying", |
| template charstring body := *) := { |
| statusLine := tr_SIP_StatusLine(status_code, reason), |
| msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, omit, |
| via, |
| method, seq_nr), |
| messageBody := body, |
| payload := omit |
| } |
| |
| /* 180 Ringing */ |
| template (present) PDU_SIP_Response |
| tr_SIP_Response_Ringing( |
| template CallidString call_id, |
| template SipAddr from_addr, |
| template SipAddr to_addr, |
| template (present) Via via := tr_Via_from(?), |
| template integer seq_nr := ?, |
| template charstring method := "INVITE", |
| template integer status_code := 180, |
| template charstring reason := "Ringing", |
| template charstring body := *) := { |
| statusLine := tr_SIP_StatusLine(status_code, reason), |
| msgHeader := tr_SIP_msgh_std(call_id, from_addr, to_addr, *, |
| via, |
| method, seq_nr), |
| messageBody := body, |
| payload := omit |
| } |
| |
| /**************** |
| * FUNCTIONS: |
| ****************/ |
| |
| function f_sip_param_find(GenericParam_List li, |
| template (present) charstring id := ?) |
| return template (omit) GenericParam { |
| var integer i; |
| |
| for (i := 0; i < lengthof(li); i := i + 1) { |
| if (not ispresent(li[i])) { |
| continue; |
| } |
| if (match(li[i].id, id)) { |
| return li[i]; |
| } |
| } |
| return omit; |
| } |
| |
| function f_sip_param_find_or_fail(GenericParam_List li, |
| template (present) charstring id := ?) |
| return GenericParam { |
| var template (omit) GenericParam parameter; |
| parameter := f_sip_param_find(li, id); |
| if (istemplatekind(parameter, "omit")) { |
| Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, |
| log2str("Param ", id, " not found in ", li)); |
| } |
| return valueof(parameter); |
| } |
| |
| function f_sip_param_get_value(GenericParam_List li, |
| template (present) charstring id := ?) |
| return template (omit) charstring { |
| var template (omit) GenericParam parameter; |
| parameter := f_sip_param_find(li, id); |
| if (istemplatekind(parameter, "omit")) { |
| return omit; |
| } |
| return parameter.paramValue; |
| } |
| |
| function f_sip_param_get_value_or_fail(GenericParam_List li, |
| template (present) charstring id := ?) |
| return template (omit) charstring { |
| var GenericParam parameter; |
| parameter := f_sip_param_find_or_fail(li, id); |
| return parameter.paramValue; |
| } |
| |
| function f_sip_param_get_value_present_or_fail(GenericParam_List li, |
| template (present) charstring id := ?) |
| return charstring { |
| var GenericParam parameter; |
| parameter := f_sip_param_find_or_fail(li, id); |
| if (not ispresent(parameter.paramValue)) { |
| Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, |
| log2str("Param ", id, " value not present in ", li)); |
| } |
| return parameter.paramValue; |
| } |
| |
| function f_sip_param_match_value(GenericParam_List li, |
| template (present) charstring id := ?, |
| template charstring exp_paramValue := *) |
| return boolean { |
| var template (omit) charstring val; |
| val := f_sip_param_get_value_or_fail(li, id); |
| if (istemplatekind(val, "omit")) { |
| return istemplatekind(val, "omit") or istemplatekind(val, "*"); |
| } |
| return match(valueof(val), exp_paramValue); |
| } |
| |
| function f_sip_param_match_value_or_fail(GenericParam_List li, |
| template (present) charstring id := ?, |
| template charstring exp_paramValue := *) |
| { |
| var template (omit) charstring val := f_sip_param_get_value_or_fail(li, id); |
| if (istemplatekind(val, "omit")) { |
| if (istemplatekind(val, "omit") or istemplatekind(val, "*")) { |
| return; |
| } else { |
| Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, |
| log2str("Param ", id, " match failed: val ", val, |
| " vs exp ", exp_paramValue)); |
| } |
| } |
| if (not match(valueof(val), exp_paramValue)) { |
| Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, |
| log2str("Param ", id, " match failed: val ", val, |
| " vs exp ", exp_paramValue)); |
| } |
| } |
| |
| function f_sip_param_remove(template (omit) GenericParam_List li_tpl, charstring id) |
| return GenericParam_List { |
| var integer i; |
| var GenericParam_List li; |
| var GenericParam_List new_li := {}; |
| |
| if (istemplatekind(li_tpl, "omit")) { |
| return {}; |
| } |
| |
| li := valueof(li_tpl); |
| for (i := 0; i < lengthof(li); i := i + 1) { |
| if (not ispresent(li[i]) or |
| not match(li[i].id, id)) { |
| new_li := new_li & {li[i]}; |
| } |
| } |
| return new_li; |
| } |
| |
| function f_sip_param_set(template (omit) GenericParam_List li_tpl, charstring id, charstring val) |
| return GenericParam_List { |
| var integer i; |
| var GenericParam_List li; |
| var GenericParam_List new_li := {}; |
| var boolean found := false; |
| |
| if (istemplatekind(li_tpl, "omit")) { |
| return { valueof(ts_Param(id, val)) }; |
| } |
| |
| li := valueof(li_tpl); |
| for (i := 0; i < lengthof(li); i := i + 1) { |
| if (not ispresent(li[i]) or |
| not match(li[i].id, id)) { |
| new_li := new_li & {li[i]}; |
| continue; |
| } |
| new_li := new_li & { valueof(ts_Param(li[i].id, val)) }; |
| found := true; |
| } |
| |
| if (not found) { |
| new_li := new_li & { valueof(ts_Param(id, val)) }; |
| } |
| return new_li; |
| } |
| |
| /* Make sure string is quoted. */ |
| function f_sip_str_quote(template (value) charstring val) return charstring { |
| var charstring str := valueof(val); |
| if (lengthof(str) == 0) { |
| return ""; |
| } |
| |
| if (str[0] != "\"") { |
| return "\"" & str & "\""; |
| } |
| return str; |
| } |
| |
| /* Make sure string is unquoted. |
| * Similar to unq() in RFC 2617 */ |
| function f_sip_str_unquote(template (value) charstring val) return charstring { |
| var charstring str := valueof(val); |
| var integer len := lengthof(str); |
| |
| if (len <= 1) { |
| return str; |
| } |
| |
| if (str[0] == "\"" and str[len - 1] == "\"") { |
| return substr(str, 1, len - 2); |
| } |
| return str; |
| } |
| |
| /* RFC 2617 3.2.2.2 A1 */ |
| function f_sip_digest_A1(charstring user, charstring realm, charstring password) return charstring { |
| |
| /* RFC 2617 3.2.2.2 A1 */ |
| var charstring A1 := f_sip_str_unquote(user) & ":" & |
| f_sip_str_unquote(realm) & ":" & |
| password; |
| var charstring digestA1 := f_str_tolower(f_calculateMD5(A1)); |
| log("A1: md5('", A1, "') = ", digestA1); |
| return digestA1; |
| } |
| |
| /* RFC 2617 3.2.2.2 A2 */ |
| function f_sip_digest_A2(charstring method, charstring uri) return charstring { |
| |
| var charstring A2 := method & ":" & uri |
| var charstring digestA2 := f_str_tolower(f_calculateMD5(A2)); |
| log("A2: md5('", A2, "') = ", digestA2); |
| return digestA2; |
| } |
| |
| /* RFC 2617 3.2.2.1 Request-Digest */ |
| function f_sip_digest_RequestDigest(charstring digestA1, charstring nonce, |
| charstring nc, charstring cnonce, |
| charstring qop, charstring digestA2) return charstring { |
| var charstring digest_data := f_sip_str_unquote(nonce) & ":" & |
| nc & ":" & |
| cnonce & ":" & |
| f_sip_str_unquote(qop) & ":" & |
| digestA2; |
| var charstring req_digest := f_sip_digest_KD(digestA1, digest_data); |
| log("Request-Digest: md5('", digestA1, ":", digest_data ,"') = ", req_digest); |
| return req_digest; |
| } |
| |
| /* RFC 2617 3.2.1 The WWW-Authenticate Response Header |
| * KD(secret, data) = H(concat(secret, ":", data)) |
| */ |
| function f_sip_digest_KD(charstring secret, charstring data) return charstring { |
| return f_str_tolower(f_calculateMD5(secret & ":" & data)); |
| } |
| |
| /* Digest Auth: RFC 2617 */ |
| function f_sip_digest_gen_Authorization(WwwAuthenticate www_authenticate, |
| charstring user, charstring password, |
| charstring method, charstring uri, |
| charstring cnonce := "0a4f113b", integer nc_int := 1) return Authorization { |
| var CommaParam_List digestCln; |
| var template (value) Authorization authorization; |
| var template (value) Credentials cred; |
| var template (omit) GenericParam rx_param; |
| |
| digestCln := www_authenticate.challenge[0].digestCln; |
| |
| var charstring algorithm; |
| rx_param := f_sip_param_find(digestCln, "algorithm"); |
| if (istemplatekind(rx_param, "omit")) { |
| /* Assume MD5 if not set */ |
| algorithm := "MD5" |
| } else { |
| algorithm := valueof(rx_param.paramValue); |
| if (f_strstr(algorithm, "MD5") == -1) { |
| Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, |
| log2str("Unexpected algorithm: ", algorithm)); |
| } |
| } |
| |
| var charstring realm := f_sip_param_get_value_present_or_fail(digestCln, "realm"); |
| var charstring nonce := f_sip_param_get_value_present_or_fail(digestCln, "nonce"); |
| var charstring opaque := f_sip_param_get_value_present_or_fail(digestCln, "opaque"); |
| var charstring qop := f_sip_param_get_value_present_or_fail(digestCln, "qop"); |
| |
| if (f_strstr(qop, "auth") == -1) { |
| Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail, log2str("Unexpected qop: ", qop)); |
| } |
| var charstring selected_qop := "auth"; |
| |
| /* RFC 2617 3.2.2.2 A1 */ |
| var charstring digestA1 := f_sip_digest_A1(user, realm, password); |
| /* RFC 2617 3.2.2.3 A2 */ |
| var charstring digestA2 := f_sip_digest_A2(method, uri); |
| |
| /* RFC 2617 3.2.2.1 Request-Digest */ |
| var charstring nc := f_str_tolower(hex2str(int2hex(nc_int, 8))); |
| var charstring req_digest := f_sip_digest_RequestDigest(digestA1, nonce, |
| nc, cnonce, |
| selected_qop, digestA2); |
| |
| cred := ts_Credentials_DigestResponseMD5(user, realm, nonce, |
| uri, req_digest, |
| opaque, algorithm, selected_qop, cnonce, nc); |
| |
| authorization := ts_Authorization(cred); |
| return valueof(authorization); |
| } |
| |
| /* RFC 2617 3.5 Example */ |
| function f_sip_digest_selftest() { |
| /* |
| The following example assumes that an access-protected document is |
| being requested from the server via a GET request. The URI of the |
| document is "http://www.nowhere.org/dir/index.html". Both client and |
| server know that the username for this document is "Mufasa", and the |
| password is "Circle Of Life" (with one space between each of the |
| three words). |
| |
| HTTP/1.1 401 Unauthorized |
| WWW-Authenticate: Digest |
| realm="testrealm@host.com", |
| qop="auth,auth-int", |
| nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", |
| opaque="5ccc069c403ebaf9f0171e9517f40e41" |
| |
| Authorization: Digest username="Mufasa", |
| realm="testrealm@host.com", |
| nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", |
| uri="/dir/index.html", |
| qop=auth, |
| nc=00000001, |
| cnonce="0a4f113b", |
| response="6629fae49393a05397450978507c4ef1", |
| opaque="5ccc069c403ebaf9f0171e9517f40e41" |
| */ |
| var template (value) CommaParam_List digestCln := { |
| ts_Param("realm", f_sip_str_quote("testrealm@host.com")), |
| ts_Param("qop", f_sip_str_quote("auth,auth-int")), |
| ts_Param("nonce", f_sip_str_quote("dcd98b7102dd2f0e8b11d0f600bfb0c093")), |
| ts_Param("opaque", f_sip_str_quote("5ccc069c403ebaf9f0171e9517f40e41")) |
| }; |
| var template (value) WwwAuthenticate www_authenticate := |
| ts_WwwAuthenticate( { ts_Challenge_digestCln(digestCln) } ) |
| |
| var Authorization authorization := |
| f_sip_digest_gen_Authorization(valueof(www_authenticate), |
| "Mufasa", |
| "Circle Of Life", |
| "GET", |
| "/dir/index.html", |
| cnonce := "0a4f113b", |
| nc_int := 1); |
| |
| var CommaParam_List digestResp := authorization.body.digestResponse; |
| f_sip_param_match_value_or_fail(digestResp, "realm", f_sip_str_quote("testrealm@host.com")); |
| f_sip_param_match_value_or_fail(digestResp, "nonce", f_sip_str_quote("dcd98b7102dd2f0e8b11d0f600bfb0c093")); |
| f_sip_param_match_value_or_fail(digestResp, "uri", f_sip_str_quote("/dir/index.html")); |
| f_sip_param_match_value_or_fail(digestResp, "qop", "auth"); |
| f_sip_param_match_value_or_fail(digestResp, "nc", "00000001"); |
| f_sip_param_match_value_or_fail(digestResp, "cnonce", f_sip_str_quote("0a4f113b")); |
| f_sip_param_match_value_or_fail(digestResp, "response", f_sip_str_quote("6629fae49393a05397450978507c4ef1")); |
| f_sip_param_match_value_or_fail(digestResp, "opaque", f_sip_str_quote("5ccc069c403ebaf9f0171e9517f40e41")); |
| } |
| |
| /* RFC 3261 8.1.1.5: |
| * "The sequence number value MUST be expressible as a 32-bit unsigned integer |
| * and MUST be less than 2**31." |
| */ |
| function f_sip_rand_seq_nr() return integer { |
| /* 2**31 = 2147483648 */ |
| return f_rnd_int(2147483648) |
| } |
| |
| function f_sip_next_seq_nr(integer seq_nr) return integer { |
| return (seq_nr + 1) mod 2147483648; |
| } |
| |
| function f_sip_Request_inc_seq_nr(inout template (value) PDU_SIP_Request req) { |
| req.msgHeader.cSeq.seqNumber := f_sip_next_seq_nr(valueof(req.msgHeader.cSeq.seqNumber)); |
| } |
| |
| function f_sip_rand_tag() return charstring { |
| /* Tags shall have at least 32 bit of randomness */ |
| var integer rnd_int := f_rnd_int(4294967296); |
| /* Make collisions harder by appending time to the final string: */ |
| var integer ts_int := f_time_ms() mod 4294967296; |
| return hex2str(int2hex(rnd_int, 8)) & "-" & hex2str(int2hex(ts_int, 8)); |
| } |
| |
| /* Generate a "branch" tag value. |
| * RFC 3261 p.105 section 8: |
| * "A common way to create this value is to compute a |
| * cryptographic hash of the To tag, From tag, Call-ID header |
| * field, the Request-URI of the request received (before |
| * translation), the topmost Via header, and the sequence number |
| * from the CSeq header field, in addition to any Proxy-Require |
| * and Proxy-Authorization header fields that may be present. The |
| * algorithm used to compute the hash is implementation-dependent, |
| * but MD5 (RFC 1321 [35]),expressed in hexadecimal, is a reasonable |
| * choice." |
| * See also Section 8.1.1.7: |
| * "The branch ID inserted by an element compliant with this |
| * specification MUST always begin with the characters "z9hG4bK"." |
| */ |
| const charstring sip_magic_cookie := "z9hG4bK"; |
| function f_sip_gen_branch(charstring tag_to, |
| charstring tag_from, |
| charstring tag_call_id, |
| integer cseq) return charstring { |
| var charstring str := tag_to & tag_from & tag_call_id & int2str(cseq); |
| var charstring hash := f_calculateMD5(str); |
| var charstring branch := sip_magic_cookie & hash; |
| return branch; |
| } |
| |
| function f_sip_HostPort_to_str(HostPort host_port) return charstring { |
| var charstring str := ""; |
| if (ispresent(host_port.host)) { |
| str := host_port.host; |
| } |
| if (ispresent(host_port.portField)) { |
| str := str & ":" & int2str(host_port.portField); |
| } |
| return str; |
| } |
| |
| function f_sip_SipUrl_to_str(SipUrl uri) return charstring { |
| var charstring str := uri.scheme & ":"; |
| if (ispresent(uri.userInfo)) { |
| str := str & uri.userInfo.userOrTelephoneSubscriber & "@"; |
| } |
| str := str & f_sip_HostPort_to_str(uri.hostPort); |
| return str; |
| } |
| |
| function f_sip_NameAddr_to_str(NameAddr naddr) return charstring { |
| if (ispresent(naddr.displayName)) { |
| return naddr.displayName & " <" & f_sip_SipUrl_to_str(naddr.addrSpec) & ">"; |
| } else { |
| return f_sip_SipUrl_to_str(naddr.addrSpec); |
| } |
| } |
| |
| function f_sip_SipAddr_to_str(SipAddr sip_addr) return charstring { |
| if (ischosen(sip_addr.addr.nameAddr)) { |
| return f_sip_NameAddr_to_str(sip_addr.addr.nameAddr); |
| } else { |
| return f_sip_SipUrl_to_str(sip_addr.addr.addrSpecUnion); |
| } |
| } |
| |
| } |