static void test_escaped_parameter(void) { belle_sip_uri_t* L_tmp; belle_sip_uri_t * L_uri = belle_sip_uri_parse("sip:[email protected];pa%3Dram=aa%40bb:5060[];o%40"); char* l_raw_uri = belle_sip_object_to_string(BELLE_SIP_OBJECT(L_uri)); belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri)); L_tmp = belle_sip_uri_parse(l_raw_uri); L_uri = BELLE_SIP_URI(belle_sip_object_clone(BELLE_SIP_OBJECT(L_tmp))); belle_sip_object_unref(BELLE_SIP_OBJECT(L_tmp)); belle_sip_free(l_raw_uri); CU_ASSERT_STRING_EQUAL(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(L_uri), "pa=ram"), "aa@bb:5060[]"); CU_ASSERT_TRUE(belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(L_uri), "o@")); CU_ASSERT_STRING_EQUAL(belle_sip_uri_get_host(L_uri), "titi.com"); belle_sip_object_unref(BELLE_SIP_OBJECT(L_uri)); }
/* * RFC 3261 SIP: Session Initiation Protocol June 2002 * 19.1.4 URI Comparison Some operations in this specification require determining whether two SIP or SIPS URIs are equivalent. In this specification, registrars need to compare bindings in Contact URIs in REGISTER requests (see Section 10.3.). SIP and SIPS URIs are compared for equality according to the following rules: */ int belle_sip_uri_equals(const belle_sip_uri_t* uri_a,const belle_sip_uri_t* uri_b) { const belle_sip_list_t * params; const char* b_param; const char* a_param; /* o A SIP and SIPS URI are never equivalent. */ if (belle_sip_uri_is_secure(uri_a)!=belle_sip_uri_is_secure(uri_b)) { return 0; } /* o Comparison of the userinfo of SIP and SIPS URIs is case- sensitive. This includes userinfo containing passwords or formatted as telephone-subscribers. Comparison of all other components of the URI is case-insensitive unless explicitly defined otherwise. */ if (uri_a->user && uri_b->user) { if (IS_EQUAL(uri_a->user,uri_b->user)) return 0; } else if (uri_a->user != uri_a->user) { return 0; } /* o The ordering of parameters and header fields is not significant in comparing SIP and SIPS URIs. o Characters other than those in the "reserved" set (see RFC 2396 [5]) are equivalent to their ""%" HEX HEX" encoding. o An IP address that is the result of a DNS lookup of a host name does not match that host name. o For two URIs to be equal, the user, password, host, and port components must match. */ if (!uri_a->host || !uri_b->host) { return 0; } else if (IS_EQUAL_CASE(uri_a->host,uri_b->host)) { return 0; } if (uri_a->port !=uri_b->port) return 0; /* A URI omitting the user component will not match a URI that includes one. A URI omitting the password component will not match a URI that includes one. A URI omitting any component with a default value will not match a URI explicitly containing that component with its default value. For instance, a URI omitting the optional port component will not match a URI explicitly declaring port 5060. The same is true for the transport-parameter, ttl-parameter, user-parameter, and method components. Defining sip:user@host to not be equivalent to sip:user@host:5060 is a change from RFC 2543. When deriving addresses from URIs, equivalent addresses are expected from equivalent URIs. The URI sip:user@host:5060 will always resolve to port 5060. The URI sip:user@host may resolve to other ports through the DNS SRV mechanisms detailed in [4]. o URI uri-parameter components are compared as follows: - Any uri-parameter appearing in both URIs must match. */ /* * - A user, ttl, or method uri-parameter appearing in only one URI never matches, even if it contains the default value. - A URI that includes an maddr parameter will not match a URI that contains no maddr parameter. * */ PARAM_CASE_CMP(uri_a,uri_b,"transport") PARAM_CASE_CMP(uri_a,uri_b,"user") PARAM_CASE_CMP(uri_a,uri_b,"ttl") PARAM_CASE_CMP(uri_a,uri_b,"method") PARAM_CASE_CMP(uri_a,uri_b,"maddr") for(params=belle_sip_parameters_get_parameters((belle_sip_parameters_t*) uri_a);params!=NULL;params=params->next) { if ((b_param=belle_sip_parameters_get_parameter((belle_sip_parameters_t*) uri_b,(const char*)params->data)) !=NULL) { if (IS_EQUAL_CASE(b_param,(const char*)params->data)) return 0; } } /* - All other uri-parameters appearing in only one URI are ignored when comparing the URIs. */ /* *fixme ignored for now*/ /* o URI header components are never ignored. Any present header component MUST be present in both URIs and match for the URIs to match. The matching rules are defined for each header field in Section 20. */ return 1; }
const char* belle_sip_uri_get_header(const belle_sip_uri_t* uri,const char* name) { return belle_sip_parameters_get_parameter(uri->header_list,name); }
void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *event){ belle_sip_request_t* req = belle_sip_request_event_get_request(event); belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,req); belle_sip_header_address_t* address; belle_sip_header_from_t* from_header; belle_sip_header_content_type_t* content_type; belle_sip_response_t* resp; int errcode=500; belle_sip_header_call_id_t* call_id = belle_sip_message_get_header_by_type(req,belle_sip_header_call_id_t); belle_sip_header_cseq_t* cseq = belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t); belle_sip_header_date_t *date=belle_sip_message_get_header_by_type(req,belle_sip_header_date_t); char* from; bool_t plain_text=FALSE; bool_t external_body=FALSE; bool_t cipher_xml=FALSE; bool_t rcs_filetransfer=FALSE; uint8_t *decryptedMessage = NULL; from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); content_type=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_content_type_t); /* check if we have a xml/cipher message to be decrypted */ if (content_type && (cipher_xml=is_cipher_xml(content_type))) { /* access the zrtp cache to get keys needed to decipher the message */ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); FILE *CACHEFD = fopen(lc->zrtp_secrets_cache, "rb+"); if (CACHEFD == NULL) { ms_warning("Unable to access ZRTP ZID cache to decrypt message"); goto error; } else { size_t cacheSize; char *cacheString; int retval; xmlDocPtr cacheXml; cacheString=ms_load_file_content(CACHEFD, &cacheSize); if (!cacheString){ ms_warning("Unable to load content of ZRTP ZID cache to decrypt message"); goto error; } cacheString[cacheSize] = '\0'; cacheSize += 1; fclose(CACHEFD); cacheXml = xmlParseDoc((xmlChar*)cacheString); ms_free(cacheString); retval = lime_decryptMultipartMessage(cacheXml, (uint8_t *)belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)), &decryptedMessage); if (retval != 0) { ms_warning("Unable to decrypt message, reason : %s - op [%p]", lime_error_code_to_string(retval), op); free(decryptedMessage); xmlFreeDoc(cacheXml); errcode = 488; goto error; } else { /* dump updated cache to a string */ xmlChar *xmlStringOutput; int xmlStringLength; xmlDocDumpFormatMemoryEnc(cacheXml, &xmlStringOutput, &xmlStringLength, "UTF-8", 0); /* write it to the cache file */ CACHEFD = fopen(lc->zrtp_secrets_cache, "wb+"); if (fwrite(xmlStringOutput, 1, xmlStringLength, CACHEFD)<=0){ ms_warning("Fail to write cache"); } xmlFree(xmlStringOutput); fclose(CACHEFD); } xmlFreeDoc(cacheXml); } } rcs_filetransfer=is_rcs_filetransfer(content_type); if (content_type && ((plain_text=is_plain_text(content_type)) || (external_body=is_external_body(content_type)) || (decryptedMessage!=NULL) || rcs_filetransfer)) { SalMessage salmsg; char message_id[256]={0}; if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); op->pending_server_trans=server_transaction; belle_sip_object_ref(op->pending_server_trans); address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); from=belle_sip_object_to_string(BELLE_SIP_OBJECT(address)); snprintf(message_id,sizeof(message_id)-1,"%s%i" ,belle_sip_header_call_id_get_call_id(call_id) ,belle_sip_header_cseq_get_seq_number(cseq)); salmsg.from=from; /* if we just deciphered a message, use the deciphered part(which can be a rcs xml body pointing to the file to retreive from server)*/ if (cipher_xml) { salmsg.text = (char *)decryptedMessage; } else { /* message body wasn't ciphered */ salmsg.text=(plain_text||rcs_filetransfer)?belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)):NULL; } salmsg.url=NULL; salmsg.content_type = NULL; if (rcs_filetransfer) { /* if we have a rcs file transfer, set the type, message body (stored in salmsg.text) contains all needed information to retrieve the file */ salmsg.content_type = "application/vnd.gsma.rcs-ft-http+xml"; } if (external_body && belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")) { size_t url_length=strlen(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")); salmsg.url = ms_strdup(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")+1); /* skip first "*/ ((char*)salmsg.url)[url_length-2]='\0'; /*remove trailing "*/ } salmsg.message_id=message_id; salmsg.time=date ? belle_sip_header_date_get_time(date) : time(NULL); op->base.root->callbacks.text_received(op,&salmsg); free(decryptedMessage); belle_sip_object_unref(address); belle_sip_free(from); if (salmsg.url) ms_free((char*)salmsg.url); } else if (content_type && is_im_iscomposing(content_type)) { SalIsComposing saliscomposing; address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); from=belle_sip_object_to_string(BELLE_SIP_OBJECT(address)); saliscomposing.from=from; saliscomposing.text=belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); op->base.root->callbacks.is_composing_received(op,&saliscomposing); resp = belle_sip_response_create_from_request(req,200); belle_sip_server_transaction_send_response(server_transaction,resp); belle_sip_object_unref(address); belle_sip_free(from); } else { ms_error("Unsupported MESSAGE (content-type not recognized)"); resp = belle_sip_response_create_from_request(req,415); add_message_accept((belle_sip_message_t*)resp); belle_sip_server_transaction_send_response(server_transaction,resp); sal_op_release(op); return; } return; error: resp = belle_sip_response_create_from_request(req, errcode); belle_sip_server_transaction_send_response(server_transaction,resp); sal_op_release(op); }
void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *event){ belle_sip_request_t* req = belle_sip_request_event_get_request(event); belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,req); belle_sip_header_address_t* address; belle_sip_header_from_t* from_header; belle_sip_header_content_type_t* content_type; belle_sip_response_t* resp; belle_sip_header_call_id_t* call_id = belle_sip_message_get_header_by_type(req,belle_sip_header_call_id_t); belle_sip_header_cseq_t* cseq = belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t); belle_sip_header_date_t *date=belle_sip_message_get_header_by_type(req,belle_sip_header_date_t); char* from; bool_t plain_text=FALSE; bool_t external_body=FALSE; from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); content_type=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_content_type_t); if (content_type && ((plain_text=is_plain_text(content_type)) || (external_body=is_external_body(content_type)))) { SalMessage salmsg; char message_id[256]={0}; if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); op->pending_server_trans=server_transaction; belle_sip_object_ref(op->pending_server_trans); address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); from=belle_sip_object_to_string(BELLE_SIP_OBJECT(address)); snprintf(message_id,sizeof(message_id)-1,"%s%i" ,belle_sip_header_call_id_get_call_id(call_id) ,belle_sip_header_cseq_get_seq_number(cseq)); salmsg.from=from; salmsg.text=plain_text?belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)):NULL; salmsg.url=NULL; if (external_body && belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")) { size_t url_length=strlen(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")); salmsg.url = ms_strdup(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")+1); /* skip first "*/ ((char*)salmsg.url)[url_length-2]='\0'; /*remove trailing "*/ } salmsg.message_id=message_id; salmsg.time=date ? belle_sip_header_date_get_time(date) : time(NULL); op->base.root->callbacks.text_received(op,&salmsg); belle_sip_object_unref(address); belle_sip_free(from); if (salmsg.url) ms_free((char*)salmsg.url); } else if (content_type && is_im_iscomposing(content_type)) { SalIsComposing saliscomposing; address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); from=belle_sip_object_to_string(BELLE_SIP_OBJECT(address)); saliscomposing.from=from; saliscomposing.text=belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); op->base.root->callbacks.is_composing_received(op,&saliscomposing); resp = belle_sip_response_create_from_request(req,200); belle_sip_server_transaction_send_response(server_transaction,resp); belle_sip_object_unref(address); belle_sip_free(from); } else { ms_error("Unsupported MESSAGE with content type [%s/%s]",belle_sip_header_content_type_get_type(content_type) ,belle_sip_header_content_type_get_subtype(content_type)); resp = belle_sip_response_create_from_request(req,415); add_message_accept((belle_sip_message_t*)resp); belle_sip_server_transaction_send_response(server_transaction,resp); return; } }
const char * sal_address_get_uri_param(const SalAddress *addr, const char *name) { belle_sip_parameters_t* parameters = BELLE_SIP_PARAMETERS(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(addr))); return belle_sip_parameters_get_parameter(parameters, name); }
const char * sal_address_get_param(const SalAddress *addr, const char *name) { belle_sip_parameters_t* parameters = BELLE_SIP_PARAMETERS(addr); return belle_sip_parameters_get_parameter(parameters, name); }